@motebit/protocol 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,457 @@
1
+ /**
2
+ * Retention policy — three shapes, one signed deletion-certificate union,
3
+ * sensitivity ceilings as interop law, reference defaults below them.
4
+ *
5
+ * Permissive floor (Apache-2.0). Type-only file — no I/O, no algorithms
6
+ * that bind the runtime. Verifiers and signers live in `@motebit/crypto`;
7
+ * runtime-validation schemas live in `@motebit/wire-schemas`; the
8
+ * judgment of which retention shape a store registers under lives in the
9
+ * BSL packages that hold those stores. Adding a new retention shape is
10
+ * an additive `kind: "..."` entry here plus a new dispatch arm in
11
+ * `verifyDeletionCertificate` — never a rename of an existing one.
12
+ *
13
+ * Doctrine: docs/doctrine/retention-policy.md.
14
+ */
15
+ import type { MotebitId, NodeId } from "./index.js";
16
+ import type { SuiteId } from "./crypto-suite.js";
17
+ /** A ceiling for retention in days, or `Infinity` for "no upper bound." */
18
+ export type RetentionCeilingDays = number;
19
+ /**
20
+ * Protocol-stated UPPER BOUND on retention, by sensitivity level.
21
+ * Compliant implementations MUST enforce a finite ceiling for
22
+ * `medical | financial | secret` and MAY enforce one for `personal`.
23
+ * `none` is `Infinity` by law. Operators MAY ship a stricter policy.
24
+ *
25
+ * Federation peers compare retention claims against these values. An
26
+ * operator manifest declaring retention beyond a ceiling is non-conforming.
27
+ */
28
+ export declare const MAX_RETENTION_DAYS_BY_SENSITIVITY: Readonly<{
29
+ none: RetentionCeilingDays;
30
+ personal: RetentionCeilingDays;
31
+ medical: RetentionCeilingDays;
32
+ financial: RetentionCeilingDays;
33
+ secret: RetentionCeilingDays;
34
+ }>;
35
+ /**
36
+ * Reference defaults — what motebit's canonical relay enforces today.
37
+ * At-or-below `MAX_RETENTION_DAYS_BY_SENSITIVITY` for every level. An
38
+ * alternative implementation MAY override and remain interop-compliant
39
+ * so long as its values are at-or-below the ceiling.
40
+ *
41
+ * `@motebit/privacy-layer` consumes these as the in-runtime defaults; a
42
+ * parity test asserts `REFERENCE_RETENTION_DAYS_BY_SENSITIVITY[k] <=
43
+ * MAX_RETENTION_DAYS_BY_SENSITIVITY[k]` for every key.
44
+ */
45
+ export declare const REFERENCE_RETENTION_DAYS_BY_SENSITIVITY: Readonly<{
46
+ none: RetentionCeilingDays;
47
+ personal: RetentionCeilingDays;
48
+ medical: RetentionCeilingDays;
49
+ financial: RetentionCeilingDays;
50
+ secret: RetentionCeilingDays;
51
+ }>;
52
+ /**
53
+ * Retention shape registered by a store. Three legitimate motions
54
+ * derived from the doctrine's droplet-physics framing:
55
+ *
56
+ * - `mutable_pruning` — interior structure where individual deletion
57
+ * is sound (memory).
58
+ * - `append_only_horizon` — audit ledgers that admit only whole-prefix
59
+ * truncation (event-log, federation audit, settlement audit).
60
+ * - `consolidation_flush` — surface flow that consolidates into memory
61
+ * or expires (conversations, tool-audit).
62
+ */
63
+ export type RetentionShape = {
64
+ readonly kind: "mutable_pruning";
65
+ /** Per-sensitivity max retention days. Enforced ≤ `MAX_RETENTION_DAYS_BY_SENSITIVITY`. */
66
+ readonly max_retention_days_by_sensitivity: Readonly<Record<string, RetentionCeilingDays>>;
67
+ /** Always `true` — the shape commits to producing signed deletion certs. */
68
+ readonly deletion_cert: true;
69
+ } | {
70
+ readonly kind: "append_only_horizon";
71
+ /** How often the store may advance its horizon. */
72
+ readonly horizon_advance_period_days: number;
73
+ /** Always `true` — the shape commits to producing signed horizon certs. */
74
+ readonly horizon_cert: true;
75
+ /**
76
+ * Whether co-witness signatures are required on horizon certs.
77
+ * Decision 9: this value is DERIVED from federation state, not
78
+ * declared. The store declares `false` for self-witnessed mode;
79
+ * the manifest layer overrides to `true` when the operator
80
+ * appears in any peer's federation graph.
81
+ */
82
+ readonly witness_required: boolean;
83
+ } | {
84
+ readonly kind: "consolidation_flush";
85
+ readonly flush_to: "memory" | "expire";
86
+ /**
87
+ * Optional per-record min-floor resolver. Examines a record and
88
+ * returns the minimum days before flush is permissible. Used for
89
+ * settlement-floor obligations on tool-audit records (decision 3).
90
+ *
91
+ * Pure or async — phase 5 reads the resolver's return type and
92
+ * picks accordingly. Stateful resolvers close over a context
93
+ * passed at store registration; the resolver itself receives the
94
+ * record and returns the floor.
95
+ */
96
+ readonly min_floor_resolver?: (record: unknown) => number | Promise<number>;
97
+ /** Always `true` — the shape commits to producing signed flush certs. */
98
+ readonly flush_cert: true;
99
+ };
100
+ /** The closed registry of Merkle algorithm identifiers. */
101
+ export type MerkleAlgo = "merkle-sha256-v1";
102
+ /**
103
+ * Federation graph anchor — Merkle commitment over the operator's
104
+ * federation peer set at `horizon_ts`. Phase 4 quorum verification
105
+ * recomputes the root from the operator's published peer set or
106
+ * verifies inclusion proofs against it.
107
+ *
108
+ * `leaf_count = 0` is the canonical self-witnessed encoding (no peers
109
+ * at `horizon_ts`); see `EMPTY_FEDERATION_GRAPH_ANCHOR`.
110
+ */
111
+ export interface FederationGraphAnchor {
112
+ readonly algo: MerkleAlgo;
113
+ /** Hex-encoded SHA-256 root. */
114
+ readonly merkle_root: string;
115
+ /** Number of peer pubkeys in the anchored set. */
116
+ readonly leaf_count: number;
117
+ }
118
+ /**
119
+ * Empty-tree federation graph anchor — the canonical self-witnessed
120
+ * encoding when an operator has no federation peers at `horizon_ts`.
121
+ *
122
+ * `merkle_root` is the hex-encoded SHA-256 of the empty byte string
123
+ * (`sha256(new Uint8Array(0))`). Verifiers in `@motebit/crypto` admit
124
+ * `append_only_horizon` certs carrying this anchor as self-witnessed —
125
+ * `witnessed_by[]` may be empty since there are no peers to solicit.
126
+ *
127
+ * Phase 4b-3 makes `federation_graph_anchor` mandatory on certs from
128
+ * federation-aware deployments; pre-4b-3 certs without the field are
129
+ * grandfathered self-witnessed (verifier policy enforces
130
+ * presence-when-peered, not presence-always).
131
+ */
132
+ export declare const EMPTY_FEDERATION_GRAPH_ANCHOR: FederationGraphAnchor;
133
+ /**
134
+ * Merkle inclusion proof — same wire shape as
135
+ * `spec/credential-anchor-v1.md` §6 (siblings ordered leaf-to-root,
136
+ * `layer_sizes` for odd-leaf-promotion detection, `leaf_index`
137
+ * positional).
138
+ */
139
+ export interface MerkleInclusionProof {
140
+ readonly siblings: string[];
141
+ readonly leaf_index: number;
142
+ readonly layer_sizes: number[];
143
+ }
144
+ export interface HorizonWitness {
145
+ readonly motebit_id: MotebitId;
146
+ /** Ed25519 signature over the cert's canonical signing payload. */
147
+ readonly signature: string;
148
+ /**
149
+ * Optional Merkle inclusion proof for the witness's pubkey against
150
+ * the cert's `federation_graph_anchor.merkle_root`. Phase 4 quorum
151
+ * mechanisms either require this (Merkle-membership verification)
152
+ * or accept signature-only witnesses. Reserved in phase 1 so phase
153
+ * 4 lands without a wire break.
154
+ */
155
+ readonly inclusion_proof?: MerkleInclusionProof;
156
+ }
157
+ /**
158
+ * Cert body the witness canonicalizes and signs. Mirrors the
159
+ * `append_only_horizon` arm of `DeletionCertificate` minus
160
+ * `witnessed_by[]` and minus `signature` — exactly the shape
161
+ * `canonicalizeHorizonCertForWitness` in `@motebit/crypto` derives at
162
+ * verification time. A peer recomputes `canonicalJson(cert_body)`,
163
+ * verifies the issuer's `issuer_signature` against it, then signs the
164
+ * same bytes with its own federation key.
165
+ */
166
+ export interface HorizonWitnessRequestBody {
167
+ readonly kind: "append_only_horizon";
168
+ readonly subject: HorizonSubject;
169
+ readonly store_id: string;
170
+ readonly horizon_ts: number;
171
+ readonly issued_at: number;
172
+ /**
173
+ * Mandatory from phase 4b-3 onward when the issuer has any federation
174
+ * peers at `horizon_ts` — the `EMPTY_FEDERATION_GRAPH_ANCHOR`
175
+ * sentinel signals self-witnessed deployments. Optional in the type
176
+ * for grandfathered pre-4b-3 callers.
177
+ */
178
+ readonly federation_graph_anchor?: FederationGraphAnchor;
179
+ readonly suite: SuiteId;
180
+ }
181
+ /**
182
+ * `POST /federation/v1/horizon/witness` request body — issuer asks a
183
+ * federation peer to co-witness a pending `append_only_horizon` cert.
184
+ *
185
+ * Peer-side flow (fail-closed throughout):
186
+ * 1. Resolve `issuer_id` → issuer's federation Ed25519 public key
187
+ * from the local `relay_peers` table; reject if unknown.
188
+ * 2. Verify `issuer_signature` against `canonicalJson(cert_body)`
189
+ * under `cert_body.suite`. The issuer-signature payload is
190
+ * byte-equal to what the witness will sign, so verification +
191
+ * signing share canonical-bytes derivation.
192
+ * 3. Sign the same bytes; return a `WitnessSolicitationResponse`
193
+ * carrying the peer's `motebit_id`, signature, and (if available)
194
+ * a Merkle inclusion proof for its pubkey against
195
+ * `cert_body.federation_graph_anchor.merkle_root`.
196
+ *
197
+ * Non-goals: the request does NOT carry `witnessed_by[]`. Witnesses
198
+ * are portable across compositions of the same body; the issuer's
199
+ * eventual cert.signature is what binds the assembled witness array.
200
+ */
201
+ export interface WitnessSolicitationRequest {
202
+ readonly cert_body: HorizonWitnessRequestBody;
203
+ /**
204
+ * Issuer's identifier — MUST match the id projected from
205
+ * `cert_body.subject` (the `motebit_id` for per-motebit horizons,
206
+ * the `operator_id` for operator-wide horizons). Disagreement is
207
+ * fail-closed at the peer.
208
+ */
209
+ readonly issuer_id: string;
210
+ /**
211
+ * Base64url-encoded Ed25519 signature by the issuer's federation key
212
+ * over `canonicalJson(cert_body)` under `cert_body.suite`. Same
213
+ * canonical bytes the witness signs — the request authenticates
214
+ * itself by the issuer's pre-commitment to the body.
215
+ */
216
+ readonly issuer_signature: string;
217
+ }
218
+ /**
219
+ * `POST /federation/v1/horizon/witness` response body — the peer's
220
+ * `HorizonWitness`. Same shape as `cert.witnessed_by[]` entries; the
221
+ * issuer copies the response verbatim into the assembled cert before
222
+ * producing its final cert.signature.
223
+ *
224
+ * Distinct named type from `HorizonWitness` for RPC-surface clarity:
225
+ * the response is the on-the-wire envelope between two relays;
226
+ * `HorizonWitness` is the type as embedded inside a published cert.
227
+ * Structurally identical — issuer-side code passes the response
228
+ * directly into `witnessed_by[]` without transformation.
229
+ */
230
+ export interface WitnessSolicitationResponse {
231
+ readonly motebit_id: MotebitId;
232
+ /**
233
+ * Base64url-encoded Ed25519 signature over the same canonical bytes
234
+ * the issuer signed in `WitnessSolicitationRequest.issuer_signature`
235
+ * (i.e. `canonicalJson(cert_body)` under `cert_body.suite`).
236
+ */
237
+ readonly signature: string;
238
+ /**
239
+ * Optional Merkle inclusion proof for the peer's federation pubkey
240
+ * against `cert_body.federation_graph_anchor.merkle_root`. Phase
241
+ * 4b-3 verifier policy admits signature-only witnesses; future
242
+ * tightening to mandatory-inclusion-proof lands by changing verifier
243
+ * policy alone — the wire shape is forward-compatible.
244
+ */
245
+ readonly inclusion_proof?: MerkleInclusionProof;
246
+ }
247
+ /** Subject (motebit) signature block. */
248
+ export interface SubjectSignature {
249
+ readonly motebit_id: MotebitId;
250
+ readonly suite: SuiteId;
251
+ readonly signature: string;
252
+ }
253
+ /** Operator signature block. */
254
+ export interface OperatorSignature {
255
+ readonly operator_id: string;
256
+ readonly suite: SuiteId;
257
+ readonly signature: string;
258
+ }
259
+ /**
260
+ * Delegate signature block — multi-hop authorization per delegation-v1
261
+ * §5.5. The delegate's identity key signs; the delegation_receipt_id
262
+ * references the receipt that authorized the retention scope.
263
+ */
264
+ export interface DelegateSignature {
265
+ readonly motebit_id: MotebitId;
266
+ readonly delegation_receipt_id: string;
267
+ readonly suite: SuiteId;
268
+ readonly signature: string;
269
+ }
270
+ /**
271
+ * Guardian signature block — enterprise custody per identity-v1 §3.3.
272
+ * Verifier MUST cross-check `guardian_public_key` against the motebit's
273
+ * identity file `guardian.public_key` field.
274
+ */
275
+ export interface GuardianSignature {
276
+ /** Hex-encoded guardian Ed25519 public key. Matches `motebit.md` §3.3 `guardian.public_key`. */
277
+ readonly guardian_public_key: string;
278
+ readonly suite: SuiteId;
279
+ readonly signature: string;
280
+ }
281
+ /**
282
+ * Reasons admitted by `mutable_pruning` and `consolidation_flush` arms.
283
+ * Each reason constrains the permitted signer set per decision 5's
284
+ * `reason × signer × mode` table. Verifiers reject certs whose
285
+ * present signature(s) don't match the reason's permitted set.
286
+ *
287
+ * `retention_enforcement_post_classification` is admitted by
288
+ * `consolidation_flush` only — it names the migration cohort under
289
+ * decision 6b's lazy-classify-on-flush path.
290
+ */
291
+ export type DeletionReason = "user_request" | "retention_enforcement" | "retention_enforcement_post_classification" | "operator_request" | "delegated_request" | "self_enforcement" | "guardian_request";
292
+ /**
293
+ * Subject discriminator on `append_only_horizon`. Per decision 8, both
294
+ * per-motebit and operator-wide horizons are first-class; effective
295
+ * horizon for any given motebit's events is `max` of both.
296
+ */
297
+ export type HorizonSubject = {
298
+ readonly kind: "motebit";
299
+ readonly motebit_id: MotebitId;
300
+ } | {
301
+ readonly kind: "operator";
302
+ readonly operator_id: string;
303
+ };
304
+ /**
305
+ * Signed retention deletion certificate. Single discriminated union by
306
+ * `kind`. New deletion shapes ship as additive registry entries; the
307
+ * verifier in `@motebit/crypto` closes under additions.
308
+ *
309
+ * Canonical signing payload (decision 5): each signature in
310
+ * `mutable_pruning` and `consolidation_flush` covers
311
+ * `canonicalJson(cert_body)` where `cert_body` is the cert with all
312
+ * `*_signature` fields removed. All present signers sign identical
313
+ * bytes — same shape as identity-v1.md §3.8.1 dual-signature succession.
314
+ * The `append_only_horizon` arm covers `canonicalJson(cert minus
315
+ * signature)`.
316
+ *
317
+ * Certificates are TERMINAL: there is no signed-revocation path. A cert
318
+ * issued in error is corrected by a follow-up cert under a different
319
+ * reason. Same foundation-law shape as delegation-v1.md §4.2 and
320
+ * migration-v1.md §3.2 terminal-state irreversibility.
321
+ */
322
+ export type DeletionCertificate = {
323
+ readonly kind: "mutable_pruning";
324
+ readonly target_id: NodeId;
325
+ readonly sensitivity: SensitivityLevelString;
326
+ readonly reason: DeletionReason;
327
+ readonly deleted_at: number;
328
+ readonly subject_signature?: SubjectSignature;
329
+ readonly operator_signature?: OperatorSignature;
330
+ readonly delegate_signature?: DelegateSignature;
331
+ readonly guardian_signature?: GuardianSignature;
332
+ } | {
333
+ readonly kind: "append_only_horizon";
334
+ readonly subject: HorizonSubject;
335
+ readonly store_id: string;
336
+ readonly horizon_ts: number;
337
+ readonly witnessed_by: HorizonWitness[];
338
+ /**
339
+ * Optional pre-4b-3, mandatory from 4b-3+. When present with
340
+ * `leaf_count = 0` (`EMPTY_FEDERATION_GRAPH_ANCHOR`) the cert is
341
+ * self-witnessed — `witnessed_by` may be empty.
342
+ */
343
+ readonly federation_graph_anchor?: FederationGraphAnchor;
344
+ readonly issued_at: number;
345
+ readonly suite: SuiteId;
346
+ readonly signature: string;
347
+ } | {
348
+ readonly kind: "consolidation_flush";
349
+ readonly target_id: string;
350
+ readonly sensitivity: SensitivityLevelString;
351
+ readonly reason: DeletionReason;
352
+ readonly flushed_to: "memory_node" | "expire";
353
+ readonly memory_node_id?: NodeId;
354
+ readonly flushed_at: number;
355
+ readonly subject_signature?: SubjectSignature;
356
+ readonly operator_signature?: OperatorSignature;
357
+ readonly delegate_signature?: DelegateSignature;
358
+ readonly guardian_signature?: GuardianSignature;
359
+ };
360
+ /**
361
+ * Sensitivity expressed as the wire string. Mirrors
362
+ * `SensitivityLevel` enum values without importing the enum (this file
363
+ * stays minimal; the enum lives in index.ts).
364
+ */
365
+ export type SensitivityLevelString = "none" | "personal" | "medical" | "financial" | "secret";
366
+ /**
367
+ * Per-store retention declaration, embedded in the operator's signed
368
+ * retention manifest. Names the registered shape and the parameters a
369
+ * verifier needs to check the operator's claims against running code.
370
+ */
371
+ export interface RetentionStoreDeclaration {
372
+ /** Stable identifier for the store within the operator's deployment. */
373
+ readonly store_id: string;
374
+ /** Human-readable name for tooling display. */
375
+ readonly store_name: string;
376
+ /** The registered retention shape. */
377
+ readonly shape: RetentionShapeDeclaration;
378
+ }
379
+ /**
380
+ * Wire-format projection of `RetentionShape` — drops the resolver
381
+ * function (a closure can't ride the wire) and surfaces declared
382
+ * parameters only. The runtime registration in BSL carries the
383
+ * resolver; the manifest declares its presence as a boolean.
384
+ */
385
+ export type RetentionShapeDeclaration = {
386
+ readonly kind: "mutable_pruning";
387
+ readonly max_retention_days_by_sensitivity: Readonly<Record<string, RetentionCeilingDays>>;
388
+ } | {
389
+ readonly kind: "append_only_horizon";
390
+ readonly horizon_advance_period_days: number;
391
+ readonly witness_required: boolean;
392
+ } | {
393
+ readonly kind: "consolidation_flush";
394
+ readonly flush_to: "memory" | "expire";
395
+ readonly has_min_floor_resolver: boolean;
396
+ };
397
+ /**
398
+ * Stable string identifier for each canonical runtime store. The
399
+ * discriminator is interop law — verifiers and tooling cross-reference
400
+ * these exact strings with the manifest's `RetentionStoreDeclaration.store_id`.
401
+ */
402
+ export type RuntimeStoreId = "memory" | "event_log" | "conversation_messages" | "tool_audit";
403
+ /**
404
+ * Canonical registry: `RuntimeStoreId` → declared `RetentionShape`.
405
+ *
406
+ * - `memory` registers under `mutable_pruning` per phase 3 — the
407
+ * privacy-layer's `deleteMemory` constructs and signs the cert at
408
+ * each erase call site.
409
+ * - `event_log` registers under `append_only_horizon` per phase 4a —
410
+ * `EventStore.advanceHorizon` signs the horizon cert and truncates.
411
+ * `witness_required: false` is the no-peer-deployment derivation
412
+ * per decision 9; the manifest layer overrides to `true` once the
413
+ * operator appears in any peer's federation graph (phase 4b-3).
414
+ * - `conversation_messages` and `tool_audit` register under
415
+ * `consolidation_flush` per phase 5-ship — the consolidation cycle's
416
+ * flush phase enforces, lazy-classifying on read per decision 6b.
417
+ * Tool-audit's settlement-floor resolver per decision 3 is wired at
418
+ * runtime; the manifest projection surfaces only its presence.
419
+ *
420
+ * Reference defaults below come from `REFERENCE_RETENTION_DAYS_BY_SENSITIVITY`;
421
+ * an alternative implementation MAY ship stricter ceilings and remain
422
+ * interop-compliant.
423
+ */
424
+ export declare const RUNTIME_RETENTION_REGISTRY: Readonly<Record<RuntimeStoreId, RetentionShapeDeclaration>>;
425
+ /**
426
+ * Signed retention manifest published at
427
+ * `/.well-known/motebit-retention.json`. Sibling to the operator
428
+ * transparency manifest (`docs/doctrine/operator-transparency.md`),
429
+ * same suite and same browser-side re-verification pattern.
430
+ *
431
+ * Decision 6b's lazy-classify-on-flush path declares its default tier
432
+ * via `pre_classification_default_sensitivity`.
433
+ */
434
+ export interface RetentionManifest {
435
+ /** Always `motebit/retention-manifest@1`. */
436
+ readonly spec: "motebit/retention-manifest@1";
437
+ /** The operator publishing this manifest. */
438
+ readonly operator_id: string;
439
+ readonly issued_at: number;
440
+ /** Per-store declarations. Drift gate enumerates against the registry. */
441
+ readonly stores: RetentionStoreDeclaration[];
442
+ /**
443
+ * Default sensitivity for un-classified pre-deploy records under
444
+ * `consolidation_flush` (decision 6b). Defaults to `"personal"` if
445
+ * absent.
446
+ */
447
+ readonly pre_classification_default_sensitivity?: SensitivityLevelString;
448
+ /**
449
+ * Honest gaps the operator declares — same pattern as
450
+ * `operator-transparency.md` § "Reference implementation". Stage 1
451
+ * ships with the chain anchor in `honest_gaps` until stage 2.
452
+ */
453
+ readonly honest_gaps?: string[];
454
+ readonly suite: SuiteId;
455
+ readonly signature: string;
456
+ }
457
+ //# sourceMappingURL=retention-policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention-policy.d.ts","sourceRoot":"","sources":["../src/retention-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Retention policy — three shapes, one signed deletion-certificate union,
3
+ * sensitivity ceilings as interop law, reference defaults below them.
4
+ *
5
+ * Permissive floor (Apache-2.0). Type-only file — no I/O, no algorithms
6
+ * that bind the runtime. Verifiers and signers live in `@motebit/crypto`;
7
+ * runtime-validation schemas live in `@motebit/wire-schemas`; the
8
+ * judgment of which retention shape a store registers under lives in the
9
+ * BSL packages that hold those stores. Adding a new retention shape is
10
+ * an additive `kind: "..."` entry here plus a new dispatch arm in
11
+ * `verifyDeletionCertificate` — never a rename of an existing one.
12
+ *
13
+ * Doctrine: docs/doctrine/retention-policy.md.
14
+ */
15
+ /**
16
+ * Protocol-stated UPPER BOUND on retention, by sensitivity level.
17
+ * Compliant implementations MUST enforce a finite ceiling for
18
+ * `medical | financial | secret` and MAY enforce one for `personal`.
19
+ * `none` is `Infinity` by law. Operators MAY ship a stricter policy.
20
+ *
21
+ * Federation peers compare retention claims against these values. An
22
+ * operator manifest declaring retention beyond a ceiling is non-conforming.
23
+ */
24
+ export const MAX_RETENTION_DAYS_BY_SENSITIVITY = Object.freeze({
25
+ none: Infinity,
26
+ personal: 365,
27
+ medical: 90,
28
+ financial: 90,
29
+ secret: 30,
30
+ });
31
+ /**
32
+ * Reference defaults — what motebit's canonical relay enforces today.
33
+ * At-or-below `MAX_RETENTION_DAYS_BY_SENSITIVITY` for every level. An
34
+ * alternative implementation MAY override and remain interop-compliant
35
+ * so long as its values are at-or-below the ceiling.
36
+ *
37
+ * `@motebit/privacy-layer` consumes these as the in-runtime defaults; a
38
+ * parity test asserts `REFERENCE_RETENTION_DAYS_BY_SENSITIVITY[k] <=
39
+ * MAX_RETENTION_DAYS_BY_SENSITIVITY[k]` for every key.
40
+ */
41
+ export const REFERENCE_RETENTION_DAYS_BY_SENSITIVITY = Object.freeze({
42
+ none: Infinity,
43
+ personal: 365,
44
+ medical: 90,
45
+ financial: 90,
46
+ secret: 30,
47
+ });
48
+ /**
49
+ * Empty-tree federation graph anchor — the canonical self-witnessed
50
+ * encoding when an operator has no federation peers at `horizon_ts`.
51
+ *
52
+ * `merkle_root` is the hex-encoded SHA-256 of the empty byte string
53
+ * (`sha256(new Uint8Array(0))`). Verifiers in `@motebit/crypto` admit
54
+ * `append_only_horizon` certs carrying this anchor as self-witnessed —
55
+ * `witnessed_by[]` may be empty since there are no peers to solicit.
56
+ *
57
+ * Phase 4b-3 makes `federation_graph_anchor` mandatory on certs from
58
+ * federation-aware deployments; pre-4b-3 certs without the field are
59
+ * grandfathered self-witnessed (verifier policy enforces
60
+ * presence-when-peered, not presence-always).
61
+ */
62
+ export const EMPTY_FEDERATION_GRAPH_ANCHOR = Object.freeze({
63
+ algo: "merkle-sha256-v1",
64
+ // SHA-256 of zero bytes — well-known constant.
65
+ merkle_root: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
66
+ leaf_count: 0,
67
+ });
68
+ /**
69
+ * Canonical registry: `RuntimeStoreId` → declared `RetentionShape`.
70
+ *
71
+ * - `memory` registers under `mutable_pruning` per phase 3 — the
72
+ * privacy-layer's `deleteMemory` constructs and signs the cert at
73
+ * each erase call site.
74
+ * - `event_log` registers under `append_only_horizon` per phase 4a —
75
+ * `EventStore.advanceHorizon` signs the horizon cert and truncates.
76
+ * `witness_required: false` is the no-peer-deployment derivation
77
+ * per decision 9; the manifest layer overrides to `true` once the
78
+ * operator appears in any peer's federation graph (phase 4b-3).
79
+ * - `conversation_messages` and `tool_audit` register under
80
+ * `consolidation_flush` per phase 5-ship — the consolidation cycle's
81
+ * flush phase enforces, lazy-classifying on read per decision 6b.
82
+ * Tool-audit's settlement-floor resolver per decision 3 is wired at
83
+ * runtime; the manifest projection surfaces only its presence.
84
+ *
85
+ * Reference defaults below come from `REFERENCE_RETENTION_DAYS_BY_SENSITIVITY`;
86
+ * an alternative implementation MAY ship stricter ceilings and remain
87
+ * interop-compliant.
88
+ */
89
+ export const RUNTIME_RETENTION_REGISTRY = Object.freeze({
90
+ memory: {
91
+ kind: "mutable_pruning",
92
+ max_retention_days_by_sensitivity: REFERENCE_RETENTION_DAYS_BY_SENSITIVITY,
93
+ },
94
+ event_log: {
95
+ kind: "append_only_horizon",
96
+ horizon_advance_period_days: 365,
97
+ witness_required: false,
98
+ },
99
+ conversation_messages: {
100
+ kind: "consolidation_flush",
101
+ flush_to: "expire",
102
+ has_min_floor_resolver: false,
103
+ },
104
+ tool_audit: {
105
+ kind: "consolidation_flush",
106
+ flush_to: "expire",
107
+ has_min_floor_resolver: true,
108
+ },
109
+ });
110
+ //# sourceMappingURL=retention-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention-policy.js","sourceRoot":"","sources":["../src/retention-policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmBH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAMzC,MAAM,CAAC,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;CACX,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,uCAAuC,GAM/C,MAAM,CAAC,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,GAAG;IACb,OAAO,EAAE,EAAE;IACX,SAAS,EAAE,EAAE;IACb,MAAM,EAAE,EAAE;CACX,CAAC,CAAC;AA8FH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAA0B,MAAM,CAAC,MAAM,CAAC;IAChF,IAAI,EAAE,kBAAkB;IACxB,+CAA+C;IAC/C,WAAW,EAAE,kEAAkE;IAC/E,UAAU,EAAE,CAAC;CACd,CAAC,CAAC;AAgWH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAEnC,MAAM,CAAC,MAAM,CAAC;IAChB,MAAM,EAAE;QACN,IAAI,EAAE,iBAAiB;QACvB,iCAAiC,EAAE,uCAAuC;KAC3E;IACD,SAAS,EAAE;QACT,IAAI,EAAE,qBAAqB;QAC3B,2BAA2B,EAAE,GAAG;QAChC,gBAAgB,EAAE,KAAK;KACxB;IACD,qBAAqB,EAAE;QACrB,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,QAAQ;QAClB,sBAAsB,EAAE,KAAK;KAC9B;IACD,UAAU,EAAE;QACV,IAAI,EAAE,qBAAqB;QAC3B,QAAQ,EAAE,QAAQ;QAClB,sBAAsB,EAAE,IAAI;KAC7B;CACF,CAAC,CAAC"}