@sentropic/artifacts 0.1.4 → 0.2.1

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.
Files changed (69) hide show
  1. package/README.md +47 -0
  2. package/dist/adapters/postgres-commit.d.ts +15 -0
  3. package/dist/adapters/postgres-commit.js +80 -0
  4. package/dist/adapters/postgres.d.ts +5 -2
  5. package/dist/adapters/postgres.js +39 -0
  6. package/dist/http.d.ts +43 -30
  7. package/dist/http.js +158 -507
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +2 -0
  10. package/dist/mcp-core.d.ts +32 -39
  11. package/dist/mcp-core.js +83 -244
  12. package/dist/mcp.js +5 -5
  13. package/dist/profile/contracts.d.ts +67 -0
  14. package/dist/profile/contracts.js +31 -0
  15. package/dist/profile/index.d.ts +6 -0
  16. package/dist/profile/index.js +117 -0
  17. package/dist/profile/json.d.ts +10 -0
  18. package/dist/profile/json.js +76 -0
  19. package/dist/profile/radar.d.ts +3 -0
  20. package/dist/profile/radar.js +21 -0
  21. package/dist/profile/schemas.d.ts +6 -0
  22. package/dist/profile/schemas.js +76 -0
  23. package/dist/profile/validation.d.ts +5 -0
  24. package/dist/profile/validation.js +104 -0
  25. package/dist/profile/validators.d.ts +3 -0
  26. package/dist/profile/validators.js +51 -0
  27. package/dist/server/authorized-replay.d.ts +33 -0
  28. package/dist/server/authorized-replay.js +31 -0
  29. package/dist/server/command-identity.d.ts +52 -0
  30. package/dist/server/command-identity.js +71 -0
  31. package/dist/server/commit/brands.d.ts +7 -0
  32. package/dist/server/commit/brands.js +3 -0
  33. package/dist/server/commit/coordinator.d.ts +2 -0
  34. package/dist/server/commit/coordinator.js +729 -0
  35. package/dist/server/commit/types.d.ts +382 -0
  36. package/dist/server/commit/types.js +94 -0
  37. package/dist/server/commit-contract.d.ts +4 -0
  38. package/dist/server/commit-contract.js +2 -0
  39. package/dist/server/failures.d.ts +84 -0
  40. package/dist/server/failures.js +133 -0
  41. package/dist/server/gc.d.ts +42 -1
  42. package/dist/server/gc.js +168 -5
  43. package/dist/server/idempotency.d.ts +4 -0
  44. package/dist/server/idempotency.js +14 -0
  45. package/dist/server/lifecycle.d.ts +2 -1
  46. package/dist/server/lifecycle.js +15 -1
  47. package/dist/server/object-intents.d.ts +14 -1
  48. package/dist/server/object-intents.js +31 -0
  49. package/dist/server/outcome-contract.d.ts +3 -0
  50. package/dist/server/outcome-contract.js +3 -0
  51. package/dist/server/outcome-projection.d.ts +21 -0
  52. package/dist/server/outcome-projection.js +29 -0
  53. package/dist/server/preparation-cleanup.d.ts +31 -0
  54. package/dist/server/preparation-cleanup.js +106 -0
  55. package/dist/server/publication.d.ts +78 -0
  56. package/dist/server/publication.js +263 -31
  57. package/dist/server/service.d.ts +60 -0
  58. package/dist/server/service.js +181 -0
  59. package/dist/testing.d.ts +50 -0
  60. package/dist/testing.js +86 -0
  61. package/docs/migration-l6.md +134 -0
  62. package/examples/radar-commit-setup.ts +302 -0
  63. package/l0-freeze/command-identity-contract.ts +303 -0
  64. package/l0-freeze/commit-contract.ts +421 -0
  65. package/l0-freeze/failure-contract.ts +174 -0
  66. package/l0-freeze/profile-contract.ts +219 -0
  67. package/migrations/0003_coordinator.sql +28 -0
  68. package/package.json +27 -1
  69. package/src/contracts.ts +125 -0
@@ -0,0 +1,382 @@
1
+ /**
2
+ * L3 (immo #861) — finalization protocol types (spec r2 §§3.1–3.2).
3
+ *
4
+ * r2-exact server-side shapes, reconciled with the fixed L0 declarations:
5
+ * invocation context, commit context with nested command identity, opaque
6
+ * fence, typed authorization decision, opaque transaction plus the
7
+ * coordinator-bound policy participant, lock order and coordinator
8
+ * request/receipt types. Outcome shapes mirror the fixed success
9
+ * correlation fields (invocationId, commitState, replayed travel on every
10
+ * success). The export-map promotion of these modules is integration-owner
11
+ * work qualified in L6/L8. The public coordinator and participant satisfy
12
+ * the frozen L0 ABI; prepared-unit methods bind the L4/L5 domain adapters.
13
+ */
14
+ import type { CommitArrivalObserver, CommitBarrierObserver, CommitBarrierPoint } from '../../testing.js';
15
+ import type { commitFenceBrand, commitTransactionBrand } from './brands.js';
16
+ import type { ArtifactHostFailureMapper } from '../failures.js';
17
+ /** Version of the frozen command-codec shape (r2 C6). */
18
+ export declare const COMMAND_CODEC_VERSION: "artifacts-command/v1";
19
+ /** Server-derived internal key: distinct from any caller key. */
20
+ export type InternalIdempotencyKey = string & {
21
+ readonly __brand: 'internal-key';
22
+ };
23
+ /** Server-created identity for one durable command. */
24
+ export interface CommandIdentity {
25
+ readonly internalKey: InternalIdempotencyKey;
26
+ readonly commandHash: string;
27
+ readonly codecVersion: typeof COMMAND_CODEC_VERSION;
28
+ }
29
+ /**
30
+ * A4 participant lock order inside the finalization transaction. The
31
+ * coordinator acquires it in three groups: object locks up to and including
32
+ * `authority-revision`, then an explicit authority re-read followed by the
33
+ * `quota` callbacks and the provisional quota reservation (so the guard
34
+ * decision never precedes the quota wait), then `blob-reference-deletion-claim`
35
+ * callbacks and provisional writes. Guarded replay runs only the pre-quota
36
+ * groups: it serializes with object/ACL/policy writers but neither charges
37
+ * quota nor claims blob references.
38
+ */
39
+ export declare const PARTICIPANT_LOCK_ORDER: readonly ["binding-identity", "artifact-lifecycle", "acl", "current-pointer", "authority-revision", "quota", "blob-reference-deletion-claim"];
40
+ export type ParticipantLockClass = (typeof PARTICIPANT_LOCK_ORDER)[number];
41
+ /** Finalize or guarded replay. */
42
+ export type CommitPurpose = 'finalize' | 'replay';
43
+ /** Request-bound immutable invocation context (r2 §3.2). */
44
+ export interface ArtifactInvocationContext {
45
+ readonly invocationId: string;
46
+ readonly actorId: string;
47
+ readonly storageScopeId: string;
48
+ readonly authorizeCommit: AuthorizeCommit;
49
+ }
50
+ /** Commit context: invocation plus operation, identities, revision, purpose. */
51
+ export interface ArtifactCommitContext {
52
+ readonly invocationId: string;
53
+ readonly actorId: string;
54
+ readonly storageScopeId: string;
55
+ readonly operation: string;
56
+ readonly artifactId: string;
57
+ readonly bindingId: string;
58
+ readonly commandIdentity: CommandIdentity;
59
+ readonly policyRevision: string;
60
+ readonly purpose: CommitPurpose;
61
+ /** Coordinator-supplied decoded bytes; optional to preserve frozen L0 guard compatibility. */
62
+ readonly quotaBytes?: number;
63
+ }
64
+ /**
65
+ * Opaque fence minted by the transaction-bound policy participant. It is
66
+ * bound to one transaction, one invocation and one revision, and is
67
+ * verified by the coordinator; it cannot be synthesized from the revision
68
+ * string. This mirrors the frozen `ArtifactAuthorizationFence` role
69
+ * (`l0-freeze/commit-contract.ts`): the `transactionId` carries the binding
70
+ * to the coordinator-issued transaction, `fenceId` stays an opaque fence
71
+ * identity. `mintFence` MUST return `transactionId` equal to the transaction
72
+ * token the coordinator supplied to `createParticipant` for this
73
+ * transaction. The coordinator rejects any fence whose `transactionId`
74
+ * differs from the current transaction, whose `fenceId` is empty, whose
75
+ * invocation differs from the request, or whose revision differs from the
76
+ * freshly re-read policy revision (`invalid_object`).
77
+ */
78
+ export interface ArtifactAuthorizationFence {
79
+ readonly [commitFenceBrand]: true;
80
+ readonly fenceId: string;
81
+ readonly transactionId: string;
82
+ readonly invocationId: string;
83
+ readonly policyRevision: string;
84
+ }
85
+ export type AuthorizationDenialReason = 'denied' | 'revoked' | 'expired' | 'invalid_object' | 'unavailable';
86
+ /** Typed authorization decision: never an unqualified boolean. */
87
+ export type ArtifactAuthorizationDecision = {
88
+ readonly allowed: true;
89
+ readonly fence: ArtifactAuthorizationFence;
90
+ } | {
91
+ readonly allowed: false;
92
+ readonly reason: AuthorizationDenialReason;
93
+ readonly publicCode: string;
94
+ readonly status: number;
95
+ readonly retriable: boolean;
96
+ };
97
+ /**
98
+ * Host guard: current account/cohort/activation/object/quota policy. The
99
+ * coordinator may invoke the guard twice per finalization: once for the
100
+ * guarded decision after all lock/quota waits, and once to revalidate after
101
+ * the post-guard receipt/intent/barrier waits before COMMIT. The guard MUST
102
+ * therefore be side-effect-free (policy reads plus fence minting); only the
103
+ * second allowed decision gates the commit.
104
+ */
105
+ export type AuthorizeCommit = (context: ArtifactCommitContext, transaction: ArtifactCommitTransaction) => Promise<ArtifactAuthorizationDecision>;
106
+ /**
107
+ * Opaque transaction identity plus the host's registered
108
+ * transaction-bound policy/quota participant. No commit, rollback,
109
+ * release, SQL or connection capability for the guard. The participant
110
+ * handle is a coordinator-internal extension of the fixed opaque shape;
111
+ * fixed-typed guards still accept this object structurally.
112
+ */
113
+ export interface ArtifactCommitTransaction {
114
+ readonly [commitTransactionBrand]: true;
115
+ readonly transactionId: string;
116
+ readonly invocationId: string;
117
+ readonly policyRevision: string;
118
+ readonly participant: ArtifactCommitParticipant;
119
+ }
120
+ /**
121
+ * Current policy reads and provisional quota reservation on this
122
+ * transaction. This is the mechanism-level seam behind the frozen
123
+ * `ArtifactCommitParticipant` role (`l0-freeze/commit-contract.ts`): the
124
+ * separate revision/approval reads (instead of one bundled admission read)
125
+ * exist so the coordinator can order the authority lock before the quota
126
+ * wait (A4.4) and re-read both after post-guard waits (A4.6).
127
+ */
128
+ export interface ArtifactPolicyDriver {
129
+ /** Read the current policy revision row (shared lock) on this transaction. */
130
+ readRevision(): Promise<string>;
131
+ /** Check account/cohort/activation approval under the current revision. */
132
+ checkApproval(input: {
133
+ actorId: string;
134
+ operation: string;
135
+ }): Promise<{
136
+ approved: boolean;
137
+ reason?: AuthorizationDenialReason;
138
+ }>;
139
+ /**
140
+ * Provisionally reserve quota on this transaction. Rolls back with the
141
+ * unit when the guard denies or the unit conflicts.
142
+ */
143
+ reserveQuota(input: {
144
+ actorId: string;
145
+ operation: string;
146
+ storageScopeId: string;
147
+ bytes: number;
148
+ }): Promise<{
149
+ reserved: boolean;
150
+ }>;
151
+ /** Mint the opaque fence for an allowed decision. */
152
+ mintFence(revision: string, invocationId: string): Omit<ArtifactAuthorizationFence, typeof commitFenceBrand>;
153
+ }
154
+ /** Frozen participant ABI plus coordinator-internal policy reads and fence minting. */
155
+ export interface ArtifactCommitParticipant extends Omit<ArtifactPolicyDriver, 'reserveQuota' | 'mintFence'> {
156
+ readonly policyRevision: string;
157
+ readAdmission(input: AdmissionReadInput): Promise<AdmissionReadResult>;
158
+ reserveQuota(input: QuotaReserveInput | {
159
+ actorId: string;
160
+ operation: string;
161
+ }): Promise<{
162
+ reserved: boolean;
163
+ }>;
164
+ mintFence(revision: string, invocationId: string): ArtifactAuthorizationFence;
165
+ }
166
+ export interface AdmissionReadInput {
167
+ readonly operation: string;
168
+ readonly artifactId: string;
169
+ readonly bindingId: string;
170
+ readonly actorId: string;
171
+ readonly policyRevision: string;
172
+ }
173
+ export interface AdmissionReadResult {
174
+ readonly allowed: boolean;
175
+ readonly reason: AuthorizationDenialReason;
176
+ }
177
+ export interface QuotaReserveInput {
178
+ readonly storageScopeId: string;
179
+ readonly operation: string;
180
+ readonly bytes: number;
181
+ }
182
+ /** Factory binding a participant to one finalization connection. */
183
+ export interface CommitPolicyParticipantFactory {
184
+ createParticipant(client: FinalizeTxClient, transactionToken: string): ArtifactPolicyDriver;
185
+ }
186
+ /** Constrained transaction handle for provider-internal provisional work. */
187
+ export interface FinalizeTxClient {
188
+ query<T>(text: string, params: readonly unknown[]): Promise<{
189
+ rows: T[];
190
+ rowCount: number;
191
+ }>;
192
+ }
193
+ /** Finalization connection: coordinator-owned lifecycle plus receipt SQL. */
194
+ export interface FinalizeConnection extends FinalizeTxClient {
195
+ beginReadCommitted(): Promise<void>;
196
+ lockOperationKey(scopeId: string, internalKey: string): Promise<void>;
197
+ readReceipt(scopeId: string, internalKey: string): Promise<StoredCommitReceipt | undefined>;
198
+ insertReceipt(receipt: StoredCommitReceipt): Promise<void>;
199
+ commit(): Promise<void>;
200
+ rollback(): Promise<void>;
201
+ /**
202
+ * Return the client. Pass the failure when the session state is
203
+ * uncertain (failed COMMIT/rollback): the client is destroyed instead
204
+ * of rejoining the pool with an open transaction and held locks.
205
+ */
206
+ release(error?: unknown): void;
207
+ }
208
+ /** Executor seam: coordination row and raw finalization connections. */
209
+ export interface CommitExecutor {
210
+ ensureCoordinationRow(scopeId: string, internalKey: string): Promise<void>;
211
+ beginFinalization(): Promise<FinalizeConnection>;
212
+ }
213
+ /** One caller lock callback, run inside the coordinator transaction. */
214
+ export type CommitLockFn = (client: FinalizeTxClient) => Promise<void>;
215
+ /** Durable success receipt stored once per (scope, internal key). */
216
+ export interface StoredCommitReceipt {
217
+ readonly scopeId: string;
218
+ readonly internalKey: string;
219
+ readonly commandHash: string;
220
+ readonly codecVersion: string;
221
+ readonly receipt: unknown;
222
+ readonly createdAt: string;
223
+ }
224
+ /** Coordinator-owned test observation points. */
225
+ export type CoordinatorTestPoint = 'before_connection_acquire' | 'before_key_lock' | 'before_finalization_row_lock' | 'after_finalization_locks_before_guard' | 'after_replay_lookup_before_guard' | 'before_commit';
226
+ export declare const COORDINATOR_TEST_POINTS: readonly CommitBarrierPoint[];
227
+ /** One atomic finalization request. */
228
+ export interface FinalizeRequest {
229
+ readonly scopeId: string;
230
+ readonly internalKey: InternalIdempotencyKey;
231
+ readonly commandHash: string;
232
+ readonly codecVersion: string;
233
+ readonly invocationId: string;
234
+ readonly actorId: string;
235
+ readonly operation: string;
236
+ readonly artifactId?: string | null;
237
+ readonly bindingName?: string | null;
238
+ readonly policyRevision: string;
239
+ /** Decoded command bytes covered by the provisional quota reservation. */
240
+ readonly quotaBytes?: number;
241
+ /** Fixed class order; stable bytewise order within each class is the caller's obligation. */
242
+ readonly locks?: Partial<Record<ParticipantLockClass, CommitLockFn[]>>;
243
+ /** Provisional writes before the guard decision. */
244
+ readonly provisional?: (client: FinalizeTxClient) => Promise<void>;
245
+ /** Intent completion inside the unit, after the success insert. */
246
+ readonly finishIntents?: (client: FinalizeTxClient) => Promise<void>;
247
+ /** Preparation-abandonment hook, invoked on loser/denial paths. */
248
+ readonly noteAbandonedAttempt?: (attemptId: string) => Promise<void>;
249
+ readonly attemptId?: string;
250
+ readonly guard: AuthorizeCommit;
251
+ readonly receiptData: unknown;
252
+ /** Domain identity must still match the winner under the replay locks. */
253
+ readonly validateReplayReceipt?: (receipt: StoredCommitReceipt) => boolean;
254
+ }
255
+ /** Internal failure categories (r2 E2). */
256
+ export declare const FAILURE_CATEGORIES: readonly ["capability_unselected", "provider_unavailable", "conflict", "unauthorized_at_commit", "provider_error"];
257
+ export type FailureCategory = (typeof FAILURE_CATEGORIES)[number];
258
+ /** Frozen category-to-public projection (r2 E2). */
259
+ export interface FailureProjection {
260
+ readonly category: FailureCategory;
261
+ readonly variant?: string;
262
+ readonly httpStatus: number;
263
+ readonly publicCode: string;
264
+ /** Null when the failure happens before dispatch and creates no ledger entry. */
265
+ readonly ledgerReason: string | null;
266
+ readonly retriable: boolean;
267
+ }
268
+ export declare const FAILURE_PROJECTIONS: readonly FailureProjection[];
269
+ /**
270
+ * Classified internal failure with private cause and commit state. Carries
271
+ * the frozen `operational` kind so L3 outcomes are assignable to the frozen
272
+ * failure contract (`l0-freeze/failure-contract.ts`).
273
+ */
274
+ export interface ArtifactFailure {
275
+ readonly kind: 'operational';
276
+ readonly category: FailureCategory;
277
+ readonly variant?: string;
278
+ readonly httpStatus: number;
279
+ readonly publicCode: string;
280
+ readonly retriable: boolean;
281
+ readonly invocationId: string;
282
+ readonly operation: string;
283
+ readonly phase: string;
284
+ readonly commitState: 'not_committed' | 'committed' | 'unknown';
285
+ readonly cause: unknown;
286
+ }
287
+ /**
288
+ * Internal discriminated outcome. Success carries invocation identity,
289
+ * commit state and the replay flag alongside the result, mirroring the
290
+ * fixed success correlation fields.
291
+ */
292
+ export type ArtifactOutcome<T> = {
293
+ readonly ok: true;
294
+ readonly result: T;
295
+ readonly invocationId: string;
296
+ readonly commitState: 'committed';
297
+ readonly replayed: boolean;
298
+ } | {
299
+ readonly ok: false;
300
+ readonly failure: ArtifactFailure;
301
+ };
302
+ /** Coordinator result: the stored receipt plus fixed success correlation. */
303
+ export type FinalizeResult = ArtifactOutcome<StoredCommitReceipt>;
304
+ /** Coordinator construction options. */
305
+ export interface CommitCoordinatorOptions {
306
+ /** Trusted host wrapper classification for failures inside the atomic unit. */
307
+ readonly mapHostError?: ArtifactHostFailureMapper;
308
+ readonly executor: CommitExecutor;
309
+ readonly policy: CommitPolicyParticipantFactory;
310
+ /** Trusted domain adapters; every call resolves fresh state, including replay. */
311
+ readonly operations?: {
312
+ readonly guardedOperations: readonly string[];
313
+ finalize(input: FinalizationInput): Promise<FinalizeRequest>;
314
+ replay(input: ReplayInput): Promise<FinalizeRequest>;
315
+ };
316
+ /** Defined clock for activation-expiry evaluation; defaults to Date.now. */
317
+ readonly nowMs?: () => number;
318
+ readonly testObserver?: CommitBarrierObserver | CommitArrivalObserver;
319
+ /**
320
+ * Optional filter for observer arrivals; all coordinator points by default.
321
+ * Each armed pair pauses at most once. Only the six coordinator
322
+ * transaction points are accepted; the three preparation points
323
+ * (`before_blob_put`, `after_blob_put_before_verify`,
324
+ * `before_blob_readback`) are fired by L4 preparation adapters holding the
325
+ * same observer, never by this coordinator (preparation precedes the key
326
+ * lock per A4.2). Arming a point the coordinator never fires throws at
327
+ * construction instead of hanging a test.
328
+ */
329
+ readonly testPoints?: readonly CoordinatorTestPoint[];
330
+ }
331
+ /**
332
+ * The atomic finalization coordinator mechanism. It implements the unit
333
+ * owned by the frozen `ArtifactCommitCoordinator` role
334
+ * (`l0-freeze/commit-contract.ts`). Trusted operation bindings translate
335
+ * public frozen inputs to prepared domain units on this same coordinator.
336
+ */
337
+ export declare const COMMIT_PROTOCOL_VERSION: "artifacts-commit/v1";
338
+ export interface FinalizationRecord {
339
+ readonly internalKey: InternalIdempotencyKey;
340
+ readonly commandHash: string;
341
+ readonly codecVersion: typeof COMMAND_CODEC_VERSION;
342
+ readonly replayed: boolean;
343
+ }
344
+ export interface FinalizationInput {
345
+ readonly request: {
346
+ readonly method: string;
347
+ readonly path: string;
348
+ readonly headers: Record<string, string>;
349
+ readonly body: unknown;
350
+ };
351
+ readonly invocation: ArtifactInvocationContext;
352
+ readonly command: {
353
+ readonly operation: string;
354
+ readonly scopeBinding: string;
355
+ readonly payload: Record<string, unknown>;
356
+ readonly provenance: {
357
+ readonly kind: 'inline-original';
358
+ };
359
+ readonly identity: CommandIdentity;
360
+ };
361
+ }
362
+ export interface ReplayInput {
363
+ readonly invocation: ArtifactInvocationContext;
364
+ readonly internalKey: InternalIdempotencyKey;
365
+ }
366
+ export interface ArtifactCommitCoordinator {
367
+ readonly protocolVersion: typeof COMMIT_PROTOCOL_VERSION;
368
+ readonly guardedOperations: readonly string[];
369
+ readonly testObserver?: CommitArrivalObserver;
370
+ finalizeOperation(input: FinalizationInput): Promise<ArtifactOutcome<FinalizationRecord>>;
371
+ replayOperation(input: ReplayInput): Promise<ArtifactOutcome<FinalizationRecord>>;
372
+ /** Provider-internal prepared units; domain effects remain inside the same transaction. */
373
+ finalizePrepared(request: FinalizeRequest): Promise<FinalizeResult>;
374
+ replayPrepared(request: FinalizeRequest): Promise<FinalizeResult>;
375
+ }
376
+ /** Unknown legacy codec on a found success row: L6 projects the migration condition. */
377
+ export declare class CommitQuarantineError extends Error {
378
+ readonly scopeId: string;
379
+ readonly internalKey: string;
380
+ readonly codecVersion: string;
381
+ constructor(scopeId: string, internalKey: string, codecVersion: string);
382
+ }
@@ -0,0 +1,94 @@
1
+ /** Version of the frozen command-codec shape (r2 C6). */
2
+ export const COMMAND_CODEC_VERSION = 'artifacts-command/v1';
3
+ /**
4
+ * A4 participant lock order inside the finalization transaction. The
5
+ * coordinator acquires it in three groups: object locks up to and including
6
+ * `authority-revision`, then an explicit authority re-read followed by the
7
+ * `quota` callbacks and the provisional quota reservation (so the guard
8
+ * decision never precedes the quota wait), then `blob-reference-deletion-claim`
9
+ * callbacks and provisional writes. Guarded replay runs only the pre-quota
10
+ * groups: it serializes with object/ACL/policy writers but neither charges
11
+ * quota nor claims blob references.
12
+ */
13
+ export const PARTICIPANT_LOCK_ORDER = [
14
+ 'binding-identity',
15
+ 'artifact-lifecycle',
16
+ 'acl',
17
+ 'current-pointer',
18
+ 'authority-revision',
19
+ 'quota',
20
+ 'blob-reference-deletion-claim',
21
+ ];
22
+ export const COORDINATOR_TEST_POINTS = [
23
+ 'before_connection_acquire',
24
+ 'before_key_lock',
25
+ 'before_finalization_row_lock',
26
+ 'after_finalization_locks_before_guard',
27
+ 'after_replay_lookup_before_guard',
28
+ 'before_commit',
29
+ ];
30
+ /** Internal failure categories (r2 E2). */
31
+ export const FAILURE_CATEGORIES = [
32
+ 'capability_unselected',
33
+ 'provider_unavailable',
34
+ 'conflict',
35
+ 'unauthorized_at_commit',
36
+ 'provider_error',
37
+ ];
38
+ export const FAILURE_PROJECTIONS = [
39
+ {
40
+ category: 'capability_unselected', variant: 'unselected_operation',
41
+ httpStatus: 503, publicCode: 'capability_unavailable', ledgerReason: null,
42
+ retriable: false,
43
+ },
44
+ {
45
+ category: 'provider_unavailable', variant: 'dispatch_failure',
46
+ httpStatus: 503, publicCode: 'capability_unavailable', ledgerReason: 'provider_unavailable',
47
+ retriable: true,
48
+ },
49
+ {
50
+ category: 'conflict', variant: 'key_contention',
51
+ httpStatus: 409, publicCode: 'conflict', ledgerReason: 'provider_conflict',
52
+ retriable: false,
53
+ },
54
+ {
55
+ category: 'conflict', variant: 'quota_exhausted',
56
+ httpStatus: 409, publicCode: 'conflict', ledgerReason: 'provider_conflict',
57
+ retriable: false,
58
+ },
59
+ {
60
+ category: 'unauthorized_at_commit', variant: 'policy_denial',
61
+ httpStatus: 403, publicCode: 'access_denied', ledgerReason: 'unauthorized_at_commit',
62
+ retriable: false,
63
+ },
64
+ {
65
+ category: 'unauthorized_at_commit', variant: 'authority_unavailable',
66
+ httpStatus: 503, publicCode: 'capability_unavailable', ledgerReason: 'unauthorized_at_commit',
67
+ retriable: true,
68
+ },
69
+ {
70
+ category: 'provider_error', variant: 'unclassified',
71
+ httpStatus: 500, publicCode: 'internal_error', ledgerReason: 'provider_error',
72
+ retriable: false,
73
+ },
74
+ ];
75
+ /**
76
+ * The atomic finalization coordinator mechanism. It implements the unit
77
+ * owned by the frozen `ArtifactCommitCoordinator` role
78
+ * (`l0-freeze/commit-contract.ts`). Trusted operation bindings translate
79
+ * public frozen inputs to prepared domain units on this same coordinator.
80
+ */
81
+ export const COMMIT_PROTOCOL_VERSION = 'artifacts-commit/v1';
82
+ /** Unknown legacy codec on a found success row: L6 projects the migration condition. */
83
+ export class CommitQuarantineError extends Error {
84
+ scopeId;
85
+ internalKey;
86
+ codecVersion;
87
+ constructor(scopeId, internalKey, codecVersion) {
88
+ super(`commit quarantine: codec ${codecVersion} for ${scopeId}/${internalKey}`);
89
+ this.name = 'CommitQuarantineError';
90
+ this.scopeId = scopeId;
91
+ this.internalKey = internalKey;
92
+ this.codecVersion = codecVersion;
93
+ }
94
+ }
@@ -0,0 +1,4 @@
1
+ /** Supported trusted-host contracts; public request arguments never carry these values. */
2
+ export type { ArtifactInvocationContext, ArtifactCommitContext, ArtifactCommitTransaction, ArtifactAuthorizationDecision, ArtifactAuthorizationFence, AuthorizeCommit, ArtifactCommitParticipant, CommitPolicyParticipantFactory, FinalizeTxClient, FinalizeRequest, FinalizeResult, ArtifactCommitCoordinator, FinalizationInput, ReplayInput, FinalizationRecord, AdmissionReadInput, AdmissionReadResult, QuotaReserveInput, CommitExecutor, CommitCoordinatorOptions, ArtifactPolicyDriver, CoordinatorTestPoint, InternalIdempotencyKey, } from './commit/types.js';
3
+ export { CommitQuarantineError, PARTICIPANT_LOCK_ORDER, COMMIT_PROTOCOL_VERSION } from './commit/types.js';
4
+ export { createArtifactCommitCoordinator } from './commit/coordinator.js';
@@ -0,0 +1,2 @@
1
+ export { CommitQuarantineError, PARTICIPANT_LOCK_ORDER, COMMIT_PROTOCOL_VERSION } from './commit/types.js';
2
+ export { createArtifactCommitCoordinator } from './commit/coordinator.js';
@@ -0,0 +1,84 @@
1
+ /** Trusted server failures (r2 E1–E3). No driver text participates in classification. */
2
+ export type ArtifactCommitState = 'not_committed' | 'committed' | 'unknown';
3
+ /** Structurally identical to L0's server-derived SHA-256 internal key, never a caller key. */
4
+ export type ArtifactInternalKey = string & {
5
+ readonly __brand: 'internal-key';
6
+ };
7
+ export type ArtifactErrorKind = 'provider_unavailable' | 'command_conflict' | 'pointer_conflict' | 'unauthorized_at_commit' | 'capability_unselected' | 'admission_unavailable' | 'invalid_request' | 'anonymous' | 'access_denied' | 'not_found' | 'gone' | 'unprocessable' | 'verification_failed';
8
+ export type ArtifactFailureCategory = ArtifactFailure['category'];
9
+ interface ArtifactFailureFields {
10
+ readonly variant?: string;
11
+ readonly httpStatus: number;
12
+ readonly publicCode: string;
13
+ readonly retriable: boolean;
14
+ readonly invocationId: string;
15
+ readonly operation: string;
16
+ readonly phase: string;
17
+ readonly commitState: ArtifactCommitState;
18
+ /** Original thrown value, retained by identity and deliberately non-enumerable. */
19
+ readonly cause: unknown;
20
+ }
21
+ export interface ArtifactOperationalFailure extends ArtifactFailureFields {
22
+ readonly kind: 'operational';
23
+ readonly category: 'capability_unselected' | 'provider_unavailable' | 'conflict' | 'unauthorized_at_commit' | 'provider_error';
24
+ }
25
+ export interface ArtifactOrdinaryFailure extends Omit<ArtifactFailureFields, 'variant' | 'retriable'> {
26
+ readonly kind: 'ordinary';
27
+ readonly category: 'invalid_request' | 'not_found' | 'gone' | 'unprocessable' | 'verification_failed';
28
+ readonly retriable: false;
29
+ }
30
+ /** Entry authority outcomes are separate from ordinary and operational failures. */
31
+ export interface ArtifactAdmissionFailure extends ArtifactFailureFields {
32
+ readonly kind: 'admission';
33
+ readonly category: 'admission_unavailable' | 'anonymous' | 'access_denied';
34
+ }
35
+ export type ArtifactFailure = ArtifactOperationalFailure | ArtifactOrdinaryFailure | ArtifactAdmissionFailure;
36
+ export type ArtifactOutcome<T> = {
37
+ readonly ok: true;
38
+ readonly result: T;
39
+ readonly invocationId: string;
40
+ readonly commitState: ArtifactCommitState;
41
+ readonly replayed: boolean;
42
+ } | {
43
+ readonly ok: false;
44
+ readonly failure: ArtifactFailure;
45
+ };
46
+ /** State is supplied by the coordinator, never guessed from an error message. */
47
+ export interface ArtifactFailureContext {
48
+ readonly invocationId: string;
49
+ readonly operation: string;
50
+ readonly phase: string;
51
+ readonly commitState: ArtifactCommitState;
52
+ readonly storageScopeId?: string;
53
+ readonly operationKey?: ArtifactInternalKey;
54
+ }
55
+ /** Trusted guard's public refusal; private driver data must never populate these fields. */
56
+ export interface ArtifactPublicRefusal {
57
+ readonly allowed: false;
58
+ readonly reason: 'denied' | 'revoked' | 'expired' | 'invalid_object' | 'unavailable';
59
+ readonly status: number;
60
+ readonly publicCode: string;
61
+ readonly retriable: boolean;
62
+ }
63
+ export declare class ArtifactOperationError extends Error {
64
+ readonly kind: ArtifactErrorKind;
65
+ readonly details: {
66
+ readonly cause?: unknown;
67
+ readonly refusal?: ArtifactPublicRefusal;
68
+ };
69
+ constructor(kind: ArtifactErrorKind, details?: {
70
+ readonly cause?: unknown;
71
+ readonly refusal?: ArtifactPublicRefusal;
72
+ });
73
+ }
74
+ /** Mint only at verified per-key row contention, using the full scoped operation key. */
75
+ export declare class ArtifactKeyLockConflict extends Error {
76
+ readonly storageScopeId: string;
77
+ readonly operationKey: ArtifactInternalKey;
78
+ constructor(storageScopeId: string, operationKey: ArtifactInternalKey, cause: unknown);
79
+ }
80
+ /** Host wrappers map their own typed errors here; artifacts imports no host error classes. */
81
+ export type ArtifactHostFailureMapper = (cause: unknown) => ArtifactOperationError | undefined;
82
+ /** Pure per-invocation classification. Cleanup errors must not replace the primary cause. */
83
+ export declare function classifyArtifactFailure(cause: unknown, context: ArtifactFailureContext, mapHostError?: ArtifactHostFailureMapper): ArtifactFailure;
84
+ export {};