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
9 changes: 5 additions & 4 deletions CLAUDE.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ Rust owns contracts (D15): OpenAPI 3.1 from utoipa feeds generated TypeScript ty

### 10.5 Shells, offline, i18n, accessibility

- **Shells.** PWA baseline (`vite-plugin-pwa`, Workbox), online-first; Tauri 2 plus a Rust hardware agent for POS and desktop (W3). **Native apps (OR-34, D87):** React Native (Expo) apps are allowed as obop clients of the same REST and OpenAPI surface (OR-34). The proposal limits them to first-party apps and to cases a PWA cannot serve (recording a trip while the phone is locked is the first case), and keeps Tauri mobile out (D87, Proposed); the first app is Mileage ([spec/mobile.md](spec/mobile.md)). They would sign in through the system browser and `obop-oauth` (the D64 amendment), keep a SQLite command outbox on the device (the D13 amendment) and be revocable as `device` records (all Proposed). Nothing depends on browser hardware APIs: Safari has no WebUSB, Web Serial or WebHID [R12 s3.4].
- **Shells.** PWA baseline (`vite-plugin-pwa`, Workbox), online-first; Tauri 2 plus a Rust hardware agent for POS and desktop (W3). **Native apps (OR-34, D87):** React Native (Expo) apps are allowed as obop clients of the same REST and OpenAPI surface (OR-34), and every native app works on both Android and iOS (OR-36). The proposal limits them to first-party apps and to cases a PWA cannot serve (recording a trip while the phone is locked is the first case), and keeps Tauri mobile out (D87, Proposed); the first app is Mileage ([spec/mobile.md](spec/mobile.md)). They would sign in through the system browser and `obop-oauth` (the D64 amendment), keep a SQLite command outbox on the device (the D13 amendment) and be revocable as `device` records (all Proposed). Nothing depends on browser hardware APIs: Safari has no WebUSB, Web Serial or WebHID [R12 s3.4].
- **i18n.** Lingui, PO catalogs, an ICU MessageFormat 1 subset; PO parser and `icu` in Rust; Weblate; 12 target locales at first pack stable; machine translation is a suggestion and banned for statutory labels; RTL and CJK fixtures in CI (D34). Inputs accept `.` and `,` as decimal separators, key handling is IME-safe (`isComposing` plus a keyCode 229 guard), and totals use the shared Rust decimal crate compiled to Wasm so client and server agree (spike S4).
- **Accessibility.** WCAG 2.2 AA is a release gate: React Aria, Oxlint `jsx-a11y`, axe in Playwright, manual screen-reader passes on five flows, every drag with a non-drag path, remappable single-key shortcuts. Logical CSS only (CI bans physical margins); DTCG 2025.10 tokens compile to runtime CSS custom properties with `data-theme` and `data-density`, no per-theme bundles (D35).
- **Storefront** (Proposed, D14). Pages are versioned block JSON compiled into immutable snapshots, rendered in Rust with minijinja (also built to Wasm for editor preview) plus Vite islands hydrated through the Vite manifest; cart, account and checkout are uncached islands; checkout uses hosted payment fields, a script allow-list and CSP [R12 s7]. No Node in production; Astro, Leptos or Dioxus would each need an explicit owner waiver of the Vite+ rule (D14; Q14).
Expand Down
4 changes: 2 additions & 2 deletions docs/CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Reading notes. "Adopted" means this file fixes the spelling or contract for ever
| Account role | Lower snake_case; registry in finance 4.1.1 | `stock_valuation`, `grni`, `cogs` |
| Problem code | Lower snake_case RFC 9457 `type` slug. The CLI prints it unchanged as `error.code` and derives a coarse exit code from it (2.4) | `idempotency_key_reuse`, `field_not_readable`, `plan_stale` |
| Setting, config | Setting key `<module>.<key>`; database setting `obop.company_ids`; manifest keys as ARCHITECTURE 9.3; environment variables `OBOP_<AREA>_<NAME>` with `_FILE` for secret files (Proposed). The client areas `CLI` and `AUTH` are listed in 2.4. If the hosted sandbox (D83) needs its own settings, the Proposed reservation is the server area `OBOP_SANDBOX_<NAME>` (for example a session time to live) and a client profile named `sandbox`; no other document uses either yet (section 9.1) | `stock.lock_date`, `obop.company_ids` |
| Decision ids | As the identifier-namespace table of [DECISIONS.md](DECISIONS.md) section 4: `D1` to `D89`, `Q1` to `Q61`, constraints `F1` to `F6`, and owner rulings `OR-1` to `OR-35` (written `OR-4`, never "ruling 4"; a ruled statement cites its OR number, a Proposed one "Proposed (Dn)") | A family that shares letters with another is cited with its document or qualifier ("UI tier F2", "ENGINEERING Q-E2", "finance open question 14", "retail RP11"). Q18 (keep and qualify, or rename) is open; this file keeps and qualifies |
| Decision ids | As the identifier-namespace table of [DECISIONS.md](DECISIONS.md) section 4: `D1` to `D90`, `Q1` to `Q61`, constraints `F1` to `F6`, and owner rulings `OR-1` to `OR-37` (written `OR-4`, never "ruling 4"; a ruled statement cites its OR number, a Proposed one "Proposed (Dn)") | A family that shares letters with another is cited with its document or qualifier ("UI tier F2", "ENGINEERING Q-E2", "finance open question 14", "retail RP11"). Q18 (keep and qualify, or rename) is open; this file keeps and qualifies |

### 2.2 Vocabulary and spelling

Expand Down Expand Up @@ -519,7 +519,7 @@ These stay open. Documents keep "Proposed" wording and cite the question; this f
| `@obop/*` SDK package names and whether obop publishes anything to the npm registry | The names of the generated TypeScript SDKs and the UI SDK; the default (Q32) is no npm-registry publication, decided at W2 (OR-19), so the scope may never exist | Q32, OR-19, D3, D80 |
| The spellings of the reserved actor ids that tracked records store in `created_by` and `updated_by` (`system:internal`, `public:anonymous`, `connector:<id>`; each contains a colon, which no login can), the use of the existing group `audit.reader` for the global change feed, and whether an installed module that already uses one of the six reserved system field names (`created_at`, `updated_at`, `created_by`, `updated_by`, `row_version`, `sys_backfilled`) is grandfathered or blocks the upgrade | The values stored in every tracked record, and the field names no package may declare (the gate refuses them with a rename hint; built) | Q44, Q45, D75 |
| The spellings that D88 and D89 propose (none is built): the manifest table `[[model.rule]]` and the field key `on_delete` (values `refuse`, `cascade`, `set_null`); the error body key `assert_scope` (value `model.<model>`); the error code `delete_blocked` (status 409); the audit kind `delete_cascade` of `security_event`; the body keys `references`, `reason` and `limit` of `delete_blocked`; the `rules` key and the `on_delete` key of `/api/meta`; the label slot `rule.<key>.message`; the upgrade-diff change kind `field_on_delete`; and the setting `OBOP_DELETE_MAX_ROWS` | The package format of D52, the error table, the audit kinds, the metadata of D46 and the settings reference of DEPLOY.md | D88, D89; the setting's default is ratified as a starting value (OR-35 d) |
| The spellings that D90 proposes (built, in review): the field keys `max_length`, `min_length`, `min` and `max`; the same four keys in `/api/meta`; the error code `limit_violated` (status 400); the upgrade-diff change kind `field_limits`; the OpenAPI extension keywords `x-obop-minimum` and `x-obop-maximum` (for a decimal, which is a string); and the four constants `DEFAULT_TEXT_MAX`, `DEFAULT_LONGTEXT_MAX`, `TEXT_MAX_CAP` and `LONGTEXT_MAX_CAP` of `obop-registry` `limits.rs`, whose values (2,048, 100,000, 10,000, 1,000,000) are proposals for the product owner | The package format of D52, MODULES.md 3.3 and 3.5, the error table, the metadata of D46 and the OpenAPI document | D90 |
| The spellings that D90 proposes (built and merged, PR 33, tag `v0.2.1-r1`; the spellings stay Proposed): the field keys `max_length`, `min_length`, `min` and `max`; the same four keys in `/api/meta`; the error code `limit_violated` (status 400); the upgrade-diff change kind `field_limits`; the OpenAPI extension keywords `x-obop-minimum` and `x-obop-maximum` (for a decimal, which is a string); and the four constants `DEFAULT_TEXT_MAX`, `DEFAULT_LONGTEXT_MAX`, `TEXT_MAX_CAP` and `LONGTEXT_MAX_CAP` of `obop-registry` `limits.rs`, whose values (2,048, 100,000, 10,000, 1,000,000) are RATIFIED by OR-37 a | The package format of D52, MODULES.md 3.3 and 3.5, the error table, the metadata of D46 and the OpenAPI document | D90 |

### 9.2 Proposed rulings awaiting the owning spec

Expand Down
Loading
Loading