From 71c182af9a432606caa5d712ef728442c02ede01 Mon Sep 17 00:00:00 2001 From: adlee-was-taken Date: Sat, 25 Apr 2026 09:42:51 -0400 Subject: [PATCH] fix(ext/shared): correct AttachmentCaps field names to match Rust core The previous commit (f963ae3) used per_item_max_bytes and per_vault_*_max_bytes which don't match the Rust core's struct (per_item_max_count and per_vault_*_cap_bytes). Also fixes the per-item semantics: it's a COUNT of attachments per item, not a byte sum. Spec and plan docs updated in-place so future Task 7 cap-enforcement implementation uses the correct names + semantics. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../2026-04-24-relicario-extension-1c-gamma1.md | 14 +++++++------- ...6-04-24-relicario-extension-1c-gamma1-design.md | 6 +++--- extension/src/shared/types.ts | 7 ++++--- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/docs/superpowers/plans/2026-04-24-relicario-extension-1c-gamma1.md b/docs/superpowers/plans/2026-04-24-relicario-extension-1c-gamma1.md index 2f1c74a..7927dab 100644 --- a/docs/superpowers/plans/2026-04-24-relicario-extension-1c-gamma1.md +++ b/docs/superpowers/plans/2026-04-24-relicario-extension-1c-gamma1.md @@ -66,12 +66,13 @@ Replace the comment line and add the type definition just above the interface: ```ts /// Optional per-level caps on attachment plaintext sizes. /// All fields optional; if undefined that level is uncapped. +/// Field names mirror the Rust core's `AttachmentCaps` struct. /// γ₁ enforces; γ₂ ships the configuration UI. export interface AttachmentCaps { per_attachment_max_bytes?: number; - per_item_max_bytes?: number; - per_vault_soft_max_bytes?: number; - per_vault_hard_max_bytes?: number; + per_item_max_count?: number; // count of attachments per item, NOT bytes + per_vault_soft_cap_bytes?: number; // soft cap — warn user but allow + per_vault_hard_cap_bytes?: number; // hard cap — reject } export interface VaultSettings { @@ -1107,15 +1108,14 @@ Note: the cap-check TODO is left as a comment. Implementer should add the actual Replace the `// TODO: cap-checks` with: ```ts -const settings = (await sendMessage({ type: 'get_vault_settings' }))?.data as { settings: { attachment_caps: { per_attachment_max_bytes?: number; per_item_max_bytes?: number } } } | undefined; +const settings = (await sendMessage({ type: 'get_vault_settings' }))?.data as { settings: { attachment_caps: { per_attachment_max_bytes?: number; per_item_max_count?: number } } } | undefined; const caps = settings?.settings.attachment_caps ?? {}; if (caps.per_attachment_max_bytes && file.size > caps.per_attachment_max_bytes) { alert(`file too large (${formatBytes(file.size)} / cap ${formatBytes(caps.per_attachment_max_bytes)})`); return; } -const currentItemBytes = opts.attachments.reduce((s, a) => s + a.size, 0); -if (caps.per_item_max_bytes && currentItemBytes + file.size > caps.per_item_max_bytes) { - alert(`item attachments would exceed per-item cap (${formatBytes(currentItemBytes + file.size)} / ${formatBytes(caps.per_item_max_bytes)})`); +if (caps.per_item_max_count && opts.attachments.length + 1 > caps.per_item_max_count) { + alert(`item attachment count would exceed per-item cap (${opts.attachments.length + 1} / ${caps.per_item_max_count})`); return; } ``` diff --git a/docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma1-design.md b/docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma1-design.md index 39ddf65..e2d4cae 100644 --- a/docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma1-design.md +++ b/docs/superpowers/specs/2026-04-24-relicario-extension-1c-gamma1-design.md @@ -193,9 +193,9 @@ The blob itself (`attachments/.bin`) is written FIRST, so even if the item/m Caps live in `VaultSettings.attachment_caps` (β₂ shipped the schema; the UI is γ₂). γ₁ reads the four caps and enforces: - `per_attachment_max_bytes`: rejected at popup before sending to SW (cheap; fails fast) -- `per_item_max_bytes`: sum of plaintext sizes of all attachments on the item; rejected at popup -- `per_vault_soft_max_bytes`: sum of plaintext sizes across all items (computed from manifest summaries); shows warning toast but allows upload -- `per_vault_hard_max_bytes`: same sum; hard reject at popup +- `per_item_max_count`: count of attachments on the item (not bytes); rejected at popup +- `per_vault_soft_cap_bytes`: sum of plaintext sizes across all items (computed from manifest summaries); shows warning toast but allows upload +- `per_vault_hard_cap_bytes`: same sum; hard reject at popup If any cap is `undefined`, no limit is enforced for that level. γ₂ will surface the configuration UI; in γ₁ users without explicit caps get unlimited attachments (modulo the implementation's practical limits — large blobs work via Git Data API, but uploading a 50 MB file will be slow). diff --git a/extension/src/shared/types.ts b/extension/src/shared/types.ts index a845d52..dcc1d8c 100644 --- a/extension/src/shared/types.ts +++ b/extension/src/shared/types.ts @@ -198,12 +198,13 @@ export type HistoryRetention = /// Optional per-level caps on attachment plaintext sizes. /// All fields optional; if undefined that level is uncapped. +/// Field names mirror the Rust core's `AttachmentCaps` struct. /// γ₁ enforces; γ₂ ships the configuration UI. export interface AttachmentCaps { per_attachment_max_bytes?: number; - per_item_max_bytes?: number; - per_vault_soft_max_bytes?: number; - per_vault_hard_max_bytes?: number; + per_item_max_count?: number; // count of attachments per item, NOT bytes + per_vault_soft_cap_bytes?: number; // soft cap — warn user but allow + per_vault_hard_cap_bytes?: number; // hard cap — reject } export interface VaultSettings {