Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,26 @@ restores the image but never the schema, so keep migrations additive.
environment once. Boards link to device IDs through `board_device_ids`
(tehno32's firmware pages, cctvsp) or a firmware named after the board; a
board with a coupler image is OpenIPC-ready, derived on read, never stored.
- `internal/reports` — **owner reports**: ipctool's output, flash backups,
photos and console captures that camera owners and AI agents send to
`POST /api/v1/reports` (and `POST /api/v1/boards/identify`, which stores
nothing). Public only after `openipc reports publish`; identifiers replaced
by keyed hashes in the public copy; a backup served only with
`consent=public`. **Nothing but this package may write them**: triggers
refuse changes, board links are `ON DELETE RESTRICT`, files are
content-addressed and written once under `REPORTS_ROOT`
(`/srv/www/shared/owner-reports` -- not `shared/reports`, which is the
analytics'), and `internal/boards/survival_test.go` runs every importer
over stored reports.
- `internal/tools`, `internal/nfsro` — **ipctool for stock firmware**, which
has no curl and no TLS. ipctool's release job pushes each build to
`PUT /api/v1/tools/{name}` (OIDC, `internal/tools/PUSH.md`); nginx serves
them over plain HTTP at `http://openipc.org/ipctool` (`-mips32`, `-arm64`)
for uget, and `serve --role nfs` (the `go-nfs` container, production only)
exports the same directory read-only: portmapper, MOUNT v1/v3 and NFS v2/v3
over UDP and TCP, so `mount -o nolock openipc.org:/ipctool /tmp/o` works
as busybox does it. Handles are keyed to the client's address, so the UDP
READ path cannot be used for reflection.
- `internal/catalogue` — **the hardware catalogue is `data/catalogue/*.yml` and
nothing else** (#289). The service reads it at start; the site reads its
export. Change it by editing the YAML in a pull request, then run the export.
Expand Down
72 changes: 72 additions & 0 deletions data/locales/boards.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,85 @@ en:
title: Camera boards
heading: Your board is probably here
lede: 'Camera and recorder boards with photos, UART pinouts, specifications and, where we have them, factory flash dumps and U-Boot consoles. Match the PCB in your hand, then install OpenIPC on its SoC.'
report:
title: "Send us a board"
eyebrow: "Board catalogue"
lede: "A camera nobody has reported yet reaches the catalogue from one report: what ipctool reads off the board and, if you want to help port OpenIPC to it, the flash it came with."
shell_title: "You have a shell on the camera"
shell_lede_html: "Telnet into the stock firmware, or a UART console. Stock firmware has no curl, so ipctool comes over plain HTTP from openipc.org, fetched by <a href=\"https://github.com/OpenIPC/uget\">uget</a>: a 5 KB downloader you paste in as text."
step_uget: "1. Paste uget into the telnet session"
step_fetch: "2. Fetch ipctool and send the report"
nfs_title: "The firmware has an NFS client (most Xiongmai do)"
nfs_hint_html: "Other ways in, over UART, TFTP or an SD card: <a href=\"https://github.com/OpenIPC/ipctool#alternative-launch-methods\">ipctool's README</a>."
flag_upload: "the hardware report: SoC, sensor, flash layout, firmware versions"
flag_backup: "adds the whole flash, kept private for OpenIPC's maintainers. ipctool asks you to type yes first."
flag_public: "the backup is published with the report, once reviewed"
flag_note: "where you bought it and what it is sold as"
agent_title: "An AI coding agent is doing the digging"
agent_lede: "Give it this page. It checks the catalogue first, then sends what it found as a report of its own."
agent_prompt: "Read https://openipc.org/agents.md and follow it to identify this camera and send openipc.org a report."
agent_step1_html: "Ask <code>POST /api/v1/boards/identify</code> with ipctool's output: if the board is known, stop there, with its firmware."
agent_step2: "Collect the boot log, the U-Boot environment and, with the owner's say-so, a flash read."
agent_step3_html: "Send it all to <code>POST /api/v1/reports</code> and pass the receipt back to you."
fact1_title: "Read before it is shown"
fact1: "OpenIPC's maintainers review each report and file it under its board. Until then, only you can see it, at its receipt."
fact2_title: "Your camera stays anonymous"
fact2: "The MAC, the chip's serial and the cloud ID are replaced with hashes in everything published, in the report and in any log."
fact3_title: "A backup is private unless you say otherwise"
fact3_html: "It holds everything the camera stores, including Wi-Fi keys and passwords. It is published only if you sent it with <code>--public</code>."
nav:
boards: Camera boards
cameras:
socs:
index:
boards: Find by board or camera
boards:
report:
libc_uclibc: "ls /lib/ld-* shows ld-uClibc.so.0"
libc_glibc: "ls /lib/ld-* shows ld-linux.so.3"
uget_hint_html: "uget is linked against the camera's own C library: run <code>ls /lib/ld-*</code> first and pick what it shows. The text rebuilds itself as <code>/tmp/uget</code>. If the camera says <code>not found</code> or crashes, try the next build."
uget_build: "Build"
copy_uget: "Copy uget as text"
copied: "Copied: paste it into telnet"
copy_failed: "Could not copy. Open the text and copy it by hand:"
lookup_label: "Have a receipt?"
lookup_button: "Show its state"
status_pending: "Waiting for review"
status_published: "Published"
status_rejected: "Not published"
status_withdrawn: "Withdrawn"
backup_private: "Backup: private"
backup_public: "Backup: shared"
received: "Received from {channel}"
step_review: "A maintainer reads it and files it under its board"
step_review_hint: "Usually within a few days. This page changes when that happens."
step_published: "Published on the board's page"
step_published_hint: "Only the anonymised copy. A private backup stays private."
th_what: "What arrived"
th_size: "Size"
th_who: "Who can see it"
who_public: "Everyone, once published, with identifiers hashed"
who_private: "OpenIPC's maintainers only"
kind_report: "ipctool report"
kind_backup: "Flash backup"
kind_photo: "Photo"
kind_boot_log: "Boot log"
kind_uboot_env: "U-Boot environment"
kind_note: "Note"
kind_document: "Document"
looks_like: "Looks like {board} in the catalogue"
looks_like_why: "not certain until reviewed"
filed_under: "Filed under"
not_found: "No report has this receipt. Check the address ipctool printed."
load_failed: "The report could not be loaded. Try again in a minute."
reports_title: "Reports from owners"
reports_same_board: "same board as another report"
reports_app: "app"
reports_board: "board"
reports_yaml: "ipctool's output"
reports_ask: "Have this board?"
reports_send: "Send us its report"
reports_ask_tail: "Two owners with the same board is how a variant gets noticed."
stats_boards:
one: board
other: boards
Expand Down
72 changes: 72 additions & 0 deletions data/locales/boards.ru.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,85 @@ ru:
title: Платы камер
heading: Ваша плата, скорее всего, уже здесь
lede: 'Платы камер и регистраторов: фотографии, распиновка UART, характеристики, а где они есть — заводские дампы флеш-памяти и консоль U-Boot. Найдите плату, которая у вас в руках, и установите OpenIPC на её SoC.'
report:
title: "Прислать плату"
eyebrow: "Каталог плат"
lede: "Камера, о которой ещё никто не сообщил, попадает в каталог по одному отчёту: что ipctool прочитал с платы, а если хотите помочь с портированием OpenIPC — ещё и заводская прошивка с флеша."
shell_title: "У вас есть shell на камере"
shell_lede_html: "Telnet в заводскую прошивку или консоль UART. В заводских прошивках нет curl, поэтому ipctool скачивается с openipc.org по обычному HTTP утилитой <a href=\"https://github.com/OpenIPC/uget\">uget</a>: это загрузчик на 5 КБ, который вставляется в сессию как текст."
step_uget: "1. Вставьте uget в telnet-сессию"
step_fetch: "2. Скачайте ipctool и отправьте отчёт"
nfs_title: "В прошивке есть NFS-клиент (у большинства Xiongmai есть)"
nfs_hint_html: "Другие способы — через UART, TFTP или SD-карту: <a href=\"https://github.com/OpenIPC/ipctool#alternative-launch-methods\">README ipctool</a>."
flag_upload: "отчёт о железе: SoC, сенсор, разметка флеша, версии прошивки"
flag_backup: "добавляет весь флеш, доступный только мейнтейнерам OpenIPC. Сначала ipctool попросит ввести yes."
flag_public: "бэкап публикуется вместе с отчётом после проверки"
flag_note: "где куплена камера и под каким названием продаётся"
agent_title: "Разбирается ИИ-агент для программирования"
agent_lede: "Дайте ему эту страницу. Он сначала проверит каталог, а потом пришлёт найденное отдельным отчётом."
agent_prompt: "Read https://openipc.org/agents.md and follow it to identify this camera and send openipc.org a report."
agent_step1_html: "Спросить <code>POST /api/v1/boards/identify</code> с выводом ipctool: если плата известна — остановиться и взять её прошивку."
agent_step2: "Собрать лог загрузки, окружение U-Boot и, с согласия владельца, чтение флеша."
agent_step3_html: "Отправить всё в <code>POST /api/v1/reports</code> и вернуть вам квитанцию."
fact1_title: "Проверяется до публикации"
fact1: "Мейнтейнеры OpenIPC просматривают каждый отчёт и привязывают его к плате. До этого он виден только вам — по квитанции."
fact2_title: "Ваша камера остаётся анонимной"
fact2: "MAC, серийный номер чипа и облачный ID во всём опубликованном заменены хешами — и в отчёте, и в логах."
fact3_title: "Бэкап закрыт, если вы не решите иначе"
fact3_html: "В нём всё, что хранит камера, включая ключи Wi-Fi и пароли. Он публикуется, только если вы отправили его с <code>--public</code>."
nav:
boards: Платы камер
cameras:
socs:
index:
boards: Поиск по плате или камере
boards:
report:
libc_uclibc: "ls /lib/ld-* показывает ld-uClibc.so.0"
libc_glibc: "ls /lib/ld-* показывает ld-linux.so.3"
uget_hint_html: "uget собран под C-библиотеку самой камеры: сначала выполните <code>ls /lib/ld-*</code> и выберите то, что она показывает. Текст сам соберётся в <code>/tmp/uget</code>. Если камера ответит <code>not found</code> или упадёт — попробуйте следующую сборку."
uget_build: "Сборка"
copy_uget: "Скопировать uget как текст"
copied: "Скопировано: вставьте в telnet"
copy_failed: "Не удалось скопировать. Откройте текст и скопируйте вручную:"
lookup_label: "Есть квитанция?"
lookup_button: "Показать состояние"
status_pending: "Ждёт проверки"
status_published: "Опубликован"
status_rejected: "Не опубликован"
status_withdrawn: "Отозван"
backup_private: "Бэкап: закрытый"
backup_public: "Бэкап: открытый"
received: "Получен от {channel}"
step_review: "Мейнтейнер читает отчёт и привязывает его к плате"
step_review_hint: "Обычно за несколько дней. Эта страница изменится, когда это случится."
step_published: "Опубликован на странице платы"
step_published_hint: "Только анонимизированная копия. Закрытый бэкап остаётся закрытым."
th_what: "Что пришло"
th_size: "Размер"
th_who: "Кому видно"
who_public: "Всем после публикации, идентификаторы заменены хешами"
who_private: "Только мейнтейнерам OpenIPC"
kind_report: "Отчёт ipctool"
kind_backup: "Бэкап флеша"
kind_photo: "Фото"
kind_boot_log: "Лог загрузки"
kind_uboot_env: "Окружение U-Boot"
kind_note: "Заметка"
kind_document: "Документ"
looks_like: "Похоже на {board} из каталога"
looks_like_why: "точно станет ясно после проверки"
filed_under: "Привязан к"
not_found: "Отчёта с такой квитанцией нет. Проверьте адрес, который напечатал ipctool."
load_failed: "Не удалось загрузить отчёт. Попробуйте через минуту."
reports_title: "Отчёты владельцев"
reports_same_board: "та же плата, что в другом отчёте"
reports_app: "приложение"
reports_board: "плата"
reports_yaml: "Вывод ipctool"
reports_ask: "Есть такая плата?"
reports_send: "Пришлите её отчёт"
reports_ask_tail: "Когда у двух владельцев одна плата, так и замечают новые варианты."
stats_boards:
one: плата
few: платы
Expand Down
Loading
Loading