@hasna/capacity 0.1.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.
Files changed (44) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +74 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +6663 -0
  5. package/dist/domain/authority-evidence.d.ts +198 -0
  6. package/dist/domain/catalog.d.ts +65 -0
  7. package/dist/domain/counter.d.ts +7 -0
  8. package/dist/domain/eligibility.d.ts +4 -0
  9. package/dist/domain/ids.d.ts +47 -0
  10. package/dist/domain/invariants.d.ts +4 -0
  11. package/dist/domain/models.d.ts +300 -0
  12. package/dist/domain/native-subscription.d.ts +211 -0
  13. package/dist/domain/online-generation-receipt.d.ts +497 -0
  14. package/dist/domain/state.d.ts +19 -0
  15. package/dist/errors.d.ts +26 -0
  16. package/dist/http/handler.d.ts +3 -0
  17. package/dist/http/openapi.d.ts +1070 -0
  18. package/dist/http/stores.d.ts +20 -0
  19. package/dist/http/types.d.ts +141 -0
  20. package/dist/index.d.ts +56 -0
  21. package/dist/index.js +14909 -0
  22. package/dist/sdk/index.d.ts +8 -0
  23. package/dist/sdk/local.d.ts +5 -0
  24. package/dist/sdk/remote.d.ts +2 -0
  25. package/dist/sdk/types.d.ts +107 -0
  26. package/dist/serialization/dto.d.ts +13 -0
  27. package/dist/serialization/json.d.ts +7 -0
  28. package/dist/storage/credential-use-authorizer.d.ts +9 -0
  29. package/dist/storage/credential-verifier.d.ts +13 -0
  30. package/dist/storage/effect-dispatch.d.ts +278 -0
  31. package/dist/storage/file-recovery-ledger.d.ts +66 -0
  32. package/dist/storage/memory.d.ts +47 -0
  33. package/dist/storage/native-revocation.d.ts +10 -0
  34. package/dist/storage/postgres-config.d.ts +25 -0
  35. package/dist/storage/postgres-migrations.d.ts +10 -0
  36. package/dist/storage/postgres-migrator.d.ts +12 -0
  37. package/dist/storage/postgres.d.ts +90 -0
  38. package/dist/storage/recovery.d.ts +11 -0
  39. package/dist/storage/repository.d.ts +310 -0
  40. package/dist/storage/shared.d.ts +18 -0
  41. package/dist/storage/sqlite-migrations.d.ts +11 -0
  42. package/dist/storage/sqlite.d.ts +51 -0
  43. package/dist/version.d.ts +2 -0
  44. package/package.json +49 -0
@@ -0,0 +1,90 @@
1
+ import { SQL } from "bun";
2
+ import { type Counter } from "../domain/counter";
3
+ import type { CredentialBinding, CredentialOperation, EntityKind, EntityMap } from "../domain/models";
4
+ import { type PostgresConnectionInput } from "./postgres-config";
5
+ import type { AccountEvent, AccountsRepository, AuthorityPromotionKind, CredentialHandleEnvelope, CredentialHandleVerifier, CredentialResolutionGrant, CredentialResolutionTransport, CredentialUseAuthorizer, EligibilitySnapshot, MutationContext, MutationResult, NativeRevocationRequest, NativeRevocationResult, OutboxAcknowledgeRequest, OutboxClaimRequest, OutboxRecord, RecoveryLedger, ResolvedCredentialHandle, VerifiedAuthorityEvidenceRecord, PostgresRepositoryDoctor as SharedPostgresRepositoryDoctor } from "./repository";
6
+ export declare const POSTGRES_ADAPTER_STATUS_V1: Readonly<{
7
+ adapter: "postgres";
8
+ implemented: true;
9
+ conformanceClaim: true;
10
+ target: "self_hosted";
11
+ }>;
12
+ export type PostgresRepositoryDoctor = SharedPostgresRepositoryDoctor;
13
+ export interface PostgresAccountsRepositoryContract extends AccountsRepository {
14
+ }
15
+ export interface PostgresRepositoryAuthority {
16
+ readonly principalRef: string;
17
+ readonly identityRealm: "hasna";
18
+ readonly organizationRef: string;
19
+ readonly catalogIncarnation: string;
20
+ readonly buildDigest: string;
21
+ readonly configurationAttestationDigest: string;
22
+ readonly recoveryLedger: RecoveryLedger;
23
+ readonly credentialVerifier?: CredentialHandleVerifier;
24
+ readonly credentialUseAuthorizer?: CredentialUseAuthorizer;
25
+ }
26
+ export interface ConnectPostgresAccountsOptions extends PostgresConnectionInput, PostgresRepositoryAuthority {
27
+ readonly maxConnections?: number;
28
+ }
29
+ /**
30
+ * Self-hosted Postgres repository core. Every runtime query executes under
31
+ * `SET LOCAL ROLE accounts_runtime` and transaction-local identity settings;
32
+ * no pooled connection carries an Accounts principal between transactions.
33
+ */
34
+ export declare class PostgresAccountsRepository implements PostgresAccountsRepositoryContract {
35
+ private readonly client;
36
+ private readonly connectionSecurity;
37
+ private readonly ownsClient;
38
+ private readonly principalRef;
39
+ private readonly identityRealm;
40
+ private readonly organizationRef;
41
+ private readonly catalogIncarnation;
42
+ private readonly buildDigest;
43
+ private readonly configurationAttestationDigest;
44
+ private readonly recoveryLedger;
45
+ private readonly credentialVerifier;
46
+ private readonly credentialUseAuthorizer;
47
+ private closed;
48
+ constructor(client: SQL, authority: PostgresRepositoryAuthority, connectionSecurity?: "verify-full" | "loopback-test-only", ownsClient?: boolean);
49
+ static connect(options: ConnectPostgresAccountsOptions): PostgresAccountsRepository;
50
+ initialize(): Promise<void>;
51
+ get<K extends EntityKind>(kind: K, id: EntityMap[K]["id"]): Promise<EntityMap[K] | undefined>;
52
+ list<K extends EntityKind>(kind: K): Promise<readonly EntityMap[K][]>;
53
+ readEligibilitySnapshot(accessMethodId: EntityMap["access_method"]["id"]): Promise<EligibilitySnapshot>;
54
+ insert<K extends EntityKind>(kind: K, input: EntityMap[K], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
55
+ insertCapacityPoolWithAuthorityEvidence(input: EntityMap["capacity_pool"], inputEvidence: VerifiedAuthorityEvidenceRecord, context: MutationContext): Promise<MutationResult<EntityMap["capacity_pool"]>>;
56
+ insertCredentialBinding(input: CredentialBinding, inputHandle: CredentialHandleEnvelope, context: MutationContext): Promise<MutationResult<CredentialBinding>>;
57
+ promoteWithAuthorityEvidence<K extends AuthorityPromotionKind>(kind: K, input: EntityMap[K], expectedRevision: Counter, inputEvidence: readonly VerifiedAuthorityEvidenceRecord[], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
58
+ resolveCredentialHandle(bindingId: CredentialBinding["id"], grant: CredentialResolutionGrant, transport: CredentialResolutionTransport): Promise<ResolvedCredentialHandle>;
59
+ replace<K extends EntityKind>(kind: K, input: EntityMap[K], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
60
+ findReplacementReplay<K extends EntityKind>(kind: K, id: EntityMap[K]["id"], to: EntityMap[K]["status"], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]> | undefined>;
61
+ events(): Promise<readonly AccountEvent[]>;
62
+ credentialOperations(): Promise<readonly CredentialOperation[]>;
63
+ outbox(): Promise<readonly OutboxRecord[]>;
64
+ claimOutbox(request: OutboxClaimRequest): Promise<readonly OutboxRecord[]>;
65
+ acknowledgeOutbox(request: OutboxAcknowledgeRequest): Promise<OutboxRecord>;
66
+ revokeNativeGeneration(request: NativeRevocationRequest): Promise<NativeRevocationResult>;
67
+ doctor(): Promise<PostgresRepositoryDoctor>;
68
+ close(): Promise<void>;
69
+ private withPrincipal;
70
+ private ensureInstallation;
71
+ private readVerifiedLedgerFrontier;
72
+ private readRecoverySnapshot;
73
+ private appendRecovery;
74
+ private readOne;
75
+ private readOneForUpdate;
76
+ private insertRecord;
77
+ private updateRecord;
78
+ private requireParentOwner;
79
+ private buildHandleExpectedClaims;
80
+ private recordMutation;
81
+ private appendEventAndOutbox;
82
+ private appendCleanupOutbox;
83
+ private insertOperation;
84
+ private replay;
85
+ private readNativeRevocationResult;
86
+ private assertActor;
87
+ private assertOpen;
88
+ }
89
+ export declare function postgresSqlState(error: unknown): string | undefined;
90
+ export declare const POSTGRES_ACCOUNTS_CONTRACT_SHA256: "0d2b45c286f56452312b251b7622e009c486e2fe71fe8f2a5a59c01472eb8b2a";
@@ -0,0 +1,11 @@
1
+ import type { RecoveryFrontier, RecoveryLedger, RecoveryLedgerEntry, RecoveryLedgerReceipt } from "./repository";
2
+ export declare class InMemoryRecoveryLedger implements RecoveryLedger {
3
+ private frontier;
4
+ private readonly signingKey;
5
+ constructor(catalogIncarnation: string, signingKey?: Uint8Array);
6
+ readFreshFrontier(): RecoveryFrontier;
7
+ append(expected: RecoveryFrontier, entry: RecoveryLedgerEntry): RecoveryLedgerReceipt;
8
+ verifyFrontier(frontier: RecoveryFrontier): boolean;
9
+ private signFrontier;
10
+ }
11
+ export declare const UNAVAILABLE_RECOVERY_LEDGER: RecoveryLedger;
@@ -0,0 +1,310 @@
1
+ import type { Counter } from "../domain/counter";
2
+ import type { AccountEventId, AuthCapsuleId, CredentialBindingId, CredentialOperationId, EntityId, OutboxId } from "../domain/ids";
3
+ import type { Account, AccessMethod, AuthCapsule, CapacityPool, CredentialBinding, CredentialOperation, EntityKind, EntityMap, Entitlement } from "../domain/models";
4
+ export interface MutationContext {
5
+ readonly actorRef: string;
6
+ readonly idempotencyKey: string;
7
+ readonly reasonCode: string;
8
+ }
9
+ export interface AccountEvent {
10
+ readonly id: AccountEventId;
11
+ readonly aggregateKind: EntityKind;
12
+ readonly aggregateId: EntityId;
13
+ readonly aggregateRevision: Counter;
14
+ readonly actorRef: string;
15
+ readonly reasonCode: string;
16
+ readonly occurredAt: string;
17
+ }
18
+ export interface MutationResult<T> {
19
+ readonly record: T;
20
+ readonly eventId: AccountEventId;
21
+ readonly replayed: boolean;
22
+ }
23
+ export type AuthorityPromotionKind = "account" | "entitlement" | "capacity_pool" | "access_method";
24
+ /**
25
+ * Canonical, already cryptographically verified authority evidence persisted with
26
+ * its aggregate promotion. Repositories still validate this closed storage shape
27
+ * and atomically fence every nonce; they never accept an unsigned projection.
28
+ */
29
+ export interface VerifiedAuthorityEvidenceRecord {
30
+ readonly evidenceType: "provider_ownership" | "provider_capacity" | "entitlement_execution_policy" | "entitlement_terms" | "entitlement_data_policy" | "lane_isolation_policy" | "lane_execution_policy" | "lane_health";
31
+ readonly evidenceRef: string;
32
+ readonly subjectRef: string;
33
+ readonly aggregateKind: "provider_account" | "capacity_pool" | "entitlement" | "account_lane";
34
+ readonly aggregateId: string;
35
+ readonly aggregateRevision: Counter;
36
+ readonly identityRealm: string;
37
+ readonly issuerRef: string;
38
+ readonly issuerClass: "provider_ownership_verifier" | "provider_capacity_verifier" | "execution_policy_authority" | "terms_authority" | "adapter_health_reporter";
39
+ readonly issuerIncarnation: string;
40
+ readonly audience: string;
41
+ readonly keyId: string;
42
+ readonly issuedAt: string;
43
+ readonly expiresAt: string;
44
+ readonly nonce: string;
45
+ readonly evidenceGeneration: Counter;
46
+ readonly payloadDigest: string;
47
+ readonly envelopeDigest: string;
48
+ readonly envelopeJson: string;
49
+ }
50
+ export interface EmbeddedRepositoryDoctor {
51
+ readonly adapter: "memory" | "sqlite";
52
+ readonly schemaVersion: string;
53
+ readonly migrationChecksum: string;
54
+ readonly foreignKeys: boolean | "not_applicable";
55
+ readonly journalMode: "memory" | "wal";
56
+ readonly integrity: "ok";
57
+ readonly readiness: "ready" | "recovery_hold" | "metadata_only";
58
+ readonly recoveryFrontier: RecoveryFrontier | "unavailable";
59
+ readonly recoveryHold: boolean;
60
+ readonly positiveEligibility: boolean;
61
+ }
62
+ export interface PostgresRepositoryDoctor {
63
+ readonly adapter: "postgres";
64
+ readonly schemaVersion: string;
65
+ readonly migrationChecksum: string;
66
+ readonly foreignKeys: true;
67
+ readonly integrity: "ok";
68
+ readonly tls: "verify-full" | "loopback-test-only";
69
+ readonly rls: "forced";
70
+ readonly runtimeRole: "accounts_runtime";
71
+ readonly readiness: "ready" | "recovery_hold";
72
+ readonly recoveryFrontier: RecoveryFrontier | "unavailable";
73
+ readonly recoveryHold: boolean;
74
+ readonly positiveEligibility: boolean;
75
+ }
76
+ export type RepositoryDoctor = EmbeddedRepositoryDoctor | PostgresRepositoryDoctor;
77
+ export interface RecoveryFrontier {
78
+ readonly catalogIncarnation: string;
79
+ readonly sequence: Counter;
80
+ readonly hash: string;
81
+ readonly signatureDigest: string;
82
+ }
83
+ export interface RecoveryLedgerEntry {
84
+ readonly kind: "catalog_mutation" | "native_revocation_barrier";
85
+ readonly aggregateKind: EntityKind | "credential_operation";
86
+ readonly aggregateId: string;
87
+ readonly mutationDigest: string;
88
+ readonly occurredAt: string;
89
+ }
90
+ export interface RecoveryLedgerReceipt extends RecoveryFrontier {
91
+ readonly previousHash: string;
92
+ readonly entryDigest: string;
93
+ readonly receiptDigest: string;
94
+ }
95
+ export interface RecoveryLedger {
96
+ readFreshFrontier(): RecoveryFrontier;
97
+ append(expected: RecoveryFrontier, entry: RecoveryLedgerEntry): RecoveryLedgerReceipt;
98
+ verifyFrontier(frontier: RecoveryFrontier): boolean;
99
+ }
100
+ export interface RecoverySnapshot {
101
+ readonly matched: boolean;
102
+ readonly hold: boolean;
103
+ readonly frontier?: RecoveryFrontier;
104
+ }
105
+ /** Internal issuer-to-storage envelope. It is deliberately absent from the public package exports. */
106
+ export interface CredentialHandleEnvelope {
107
+ readonly opaqueHandle: string;
108
+ readonly issuerRef: string;
109
+ readonly audience: "accounts-local" | "accounts-self-hosted";
110
+ readonly catalogIncarnation: string;
111
+ readonly backendClass: "secrets_broker" | "workload_identity_broker" | "capsule_protected_state";
112
+ readonly ownerRef: string;
113
+ readonly providerAccountId: Account["id"];
114
+ readonly providerKey: string;
115
+ readonly capacityPoolId: CapacityPool["id"];
116
+ readonly capacityDomainRef: string;
117
+ readonly accessMethodId: AccessMethod["id"];
118
+ readonly credentialFamilyId: string;
119
+ readonly purpose: CredentialBinding["purpose"];
120
+ readonly resolver: CredentialBinding["resolver"];
121
+ readonly policyDigest: string;
122
+ readonly credentialGeneration: Counter;
123
+ readonly authCapsuleId?: AuthCapsule["id"];
124
+ readonly canonicalNodeId?: AuthCapsule["placementRef"];
125
+ readonly nodeGeneration?: Counter;
126
+ readonly placementGeneration?: Counter;
127
+ readonly issuedAt: string;
128
+ readonly expiresAt?: string;
129
+ readonly signature: string;
130
+ }
131
+ export type UnsignedCredentialHandleEnvelope = Omit<CredentialHandleEnvelope, "signature">;
132
+ export interface CredentialHandleExpectedClaims {
133
+ readonly audience: CredentialHandleEnvelope["audience"];
134
+ readonly catalogIncarnation: string;
135
+ readonly backendClass: CredentialHandleEnvelope["backendClass"];
136
+ readonly ownerRef: string;
137
+ readonly providerAccountId: Account["id"];
138
+ readonly providerKey: string;
139
+ readonly capacityPoolId: CapacityPool["id"];
140
+ readonly capacityDomainRef: string;
141
+ readonly accessMethodId: AccessMethod["id"];
142
+ readonly credentialFamilyId: string;
143
+ readonly purpose: CredentialBinding["purpose"];
144
+ readonly resolver: CredentialBinding["resolver"];
145
+ readonly policyDigest: string;
146
+ readonly credentialGeneration: Counter;
147
+ readonly authCapsuleId?: AuthCapsule["id"];
148
+ readonly canonicalNodeId?: AuthCapsule["placementRef"];
149
+ readonly nodeGeneration?: Counter;
150
+ readonly placementGeneration?: Counter;
151
+ }
152
+ export interface CredentialHandleVerification {
153
+ readonly credentialHandleAuditDigest: string;
154
+ }
155
+ export interface CredentialHandleVerifier {
156
+ verify(envelope: CredentialHandleEnvelope, expected: CredentialHandleExpectedClaims): CredentialHandleVerification;
157
+ }
158
+ export interface CredentialResolutionGrant {
159
+ readonly schema_version: "accounts.handle-resolution.v1";
160
+ readonly issuer_ref: string;
161
+ readonly provider_account_id: Account["id"];
162
+ readonly account_lane_id: AccessMethod["id"];
163
+ readonly capacity_pool_id: CapacityPool["id"];
164
+ readonly credential_binding_id: CredentialBindingId;
165
+ readonly credential_family_id: string;
166
+ readonly credential_generation: Counter;
167
+ readonly purpose: CredentialBinding["purpose"];
168
+ readonly resolver: CredentialBinding["resolver"];
169
+ readonly run_id: string;
170
+ readonly attempt_id: string;
171
+ readonly resource_lease_id: string;
172
+ readonly resource_id: string;
173
+ readonly resource_generation: Counter;
174
+ readonly operation_id: string;
175
+ readonly operation_digest: string;
176
+ readonly execution_epoch: Counter;
177
+ readonly subject_principal: string;
178
+ readonly actor_principal: string;
179
+ readonly holder_principal: string;
180
+ readonly executor_principal: string;
181
+ readonly audience: string;
182
+ readonly sender_key_thumbprint: string;
183
+ readonly catalog_incarnation: string;
184
+ readonly recovery_frontier_sequence: Counter;
185
+ readonly recovery_frontier_hash: string;
186
+ readonly request_digest: string;
187
+ readonly issued_at: string;
188
+ readonly expires_at: string;
189
+ readonly signature: string;
190
+ }
191
+ export type UnsignedCredentialResolutionGrant = Omit<CredentialResolutionGrant, "signature">;
192
+ export interface CredentialResolutionTransport {
193
+ readonly authenticatedActorPrincipal: string;
194
+ readonly authenticatedHolderPrincipal: string;
195
+ readonly authenticatedExecutorPrincipal: string;
196
+ readonly authenticatedSenderKeyThumbprint: string;
197
+ readonly audience: string;
198
+ readonly runId: string;
199
+ readonly attemptId: string;
200
+ readonly resourceLeaseId: string;
201
+ readonly resourceId: string;
202
+ readonly resourceGeneration: Counter;
203
+ readonly operationId: string;
204
+ readonly operationDigest: string;
205
+ readonly executionEpoch: Counter;
206
+ readonly requestDigest: string;
207
+ readonly now: string;
208
+ }
209
+ export interface CredentialResolutionExpected {
210
+ readonly providerAccountId: Account["id"];
211
+ readonly ownerRef: string;
212
+ readonly accessMethodId: AccessMethod["id"];
213
+ readonly capacityPoolId: CapacityPool["id"];
214
+ readonly bindingId: CredentialBindingId;
215
+ readonly credentialFamilyId: string;
216
+ readonly credentialGeneration: Counter;
217
+ readonly purpose: CredentialBinding["purpose"];
218
+ readonly resolver: CredentialBinding["resolver"];
219
+ readonly catalogIncarnation: string;
220
+ readonly recoveryFrontierSequence: Counter;
221
+ readonly recoveryFrontierHash: string;
222
+ }
223
+ export interface CredentialUseAuthorizer {
224
+ verify(grant: CredentialResolutionGrant, expected: CredentialResolutionExpected, transport: CredentialResolutionTransport): void;
225
+ }
226
+ export interface ResolvedCredentialHandle {
227
+ readonly bindingId: CredentialBindingId;
228
+ readonly opaqueHandle: string;
229
+ readonly issuerRef: string;
230
+ readonly audience: CredentialHandleEnvelope["audience"];
231
+ readonly backendClass: CredentialHandleEnvelope["backendClass"];
232
+ readonly expiresAt?: string;
233
+ }
234
+ export interface OutboxRecord {
235
+ readonly id: OutboxId;
236
+ readonly topic: "accounts.aggregate.changed" | "accounts.capsule.cleanup.requested";
237
+ readonly aggregateKind: EntityKind | "credential_operation";
238
+ readonly aggregateId: string;
239
+ readonly eventId?: AccountEventId;
240
+ readonly payloadDigest: string;
241
+ readonly payloadJson: string;
242
+ readonly status: "pending" | "in_flight" | "delivered" | "dead_letter";
243
+ readonly attemptCount: Counter;
244
+ readonly claimOwnerRef?: string;
245
+ readonly claimExpiresAt?: string;
246
+ readonly createdAt: string;
247
+ }
248
+ export interface OutboxClaimRequest {
249
+ readonly workerRef: string;
250
+ readonly limit: number;
251
+ readonly now: string;
252
+ readonly claimExpiresAt: string;
253
+ }
254
+ export interface OutboxAcknowledgeRequest {
255
+ readonly outboxId: OutboxId;
256
+ readonly workerRef: string;
257
+ readonly expectedAttemptCount: Counter;
258
+ readonly outcome: "delivered" | "retry" | "dead_letter";
259
+ readonly now: string;
260
+ }
261
+ export interface NativeRevocationRequest {
262
+ readonly capsuleId: AuthCapsuleId;
263
+ readonly bindingId: CredentialBindingId;
264
+ readonly barrierBindingId: CredentialBindingId;
265
+ readonly operationId: CredentialOperationId;
266
+ readonly expectedPoolRevision: Counter;
267
+ readonly expectedMethodRevision: Counter;
268
+ readonly expectedCapsuleRevision: Counter;
269
+ readonly expectedBindingRevision: Counter;
270
+ readonly occurredAt: string;
271
+ readonly context: MutationContext;
272
+ }
273
+ export interface NativeRevocationResult {
274
+ readonly pool: CapacityPool;
275
+ readonly method: AccessMethod;
276
+ readonly capsule: AuthCapsule;
277
+ readonly retiredBinding: CredentialBinding;
278
+ readonly barrierBinding: CredentialBinding;
279
+ readonly operation: CredentialOperation;
280
+ readonly replayed: boolean;
281
+ }
282
+ export interface EligibilitySnapshot {
283
+ readonly method?: AccessMethod;
284
+ readonly entitlement?: Entitlement;
285
+ readonly account?: Account;
286
+ readonly pool?: CapacityPool;
287
+ readonly capsules: readonly AuthCapsule[];
288
+ readonly bindings: readonly CredentialBinding[];
289
+ readonly recovery: RecoverySnapshot;
290
+ }
291
+ export interface AccountsRepository {
292
+ get<K extends EntityKind>(kind: K, id: EntityMap[K]["id"]): Promise<EntityMap[K] | undefined>;
293
+ list<K extends EntityKind>(kind: K): Promise<readonly EntityMap[K][]>;
294
+ readEligibilitySnapshot(accessMethodId: AccessMethod["id"]): Promise<EligibilitySnapshot>;
295
+ insert<K extends EntityKind>(kind: K, record: EntityMap[K], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
296
+ insertCredentialBinding(record: CredentialBinding, handle: CredentialHandleEnvelope, context: MutationContext): Promise<MutationResult<CredentialBinding>>;
297
+ insertCapacityPoolWithAuthorityEvidence(record: CapacityPool, evidence: VerifiedAuthorityEvidenceRecord, context: MutationContext): Promise<MutationResult<CapacityPool>>;
298
+ promoteWithAuthorityEvidence<K extends AuthorityPromotionKind>(kind: K, record: EntityMap[K], expectedRevision: Counter, evidence: readonly VerifiedAuthorityEvidenceRecord[], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
299
+ resolveCredentialHandle(bindingId: CredentialBindingId, grant: CredentialResolutionGrant, transport: CredentialResolutionTransport): Promise<ResolvedCredentialHandle>;
300
+ revokeNativeGeneration(request: NativeRevocationRequest): Promise<NativeRevocationResult>;
301
+ credentialOperations(): Promise<readonly CredentialOperation[]>;
302
+ outbox(): Promise<readonly OutboxRecord[]>;
303
+ claimOutbox(request: OutboxClaimRequest): Promise<readonly OutboxRecord[]>;
304
+ acknowledgeOutbox(request: OutboxAcknowledgeRequest): Promise<OutboxRecord>;
305
+ replace<K extends EntityKind>(kind: K, record: EntityMap[K], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
306
+ findReplacementReplay<K extends EntityKind>(kind: K, id: EntityMap[K]["id"], to: EntityMap[K]["status"], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]> | undefined>;
307
+ events(): Promise<readonly AccountEvent[]>;
308
+ doctor(): Promise<RepositoryDoctor>;
309
+ close(): Promise<void>;
310
+ }
@@ -0,0 +1,18 @@
1
+ import { type Counter } from "../domain/counter";
2
+ import type { EntityKind, EntityMap } from "../domain/models";
3
+ import type { CredentialBinding } from "../domain/models";
4
+ import type { AccountsRepository, CredentialHandleEnvelope, CredentialHandleExpectedClaims, MutationContext, OutboxAcknowledgeRequest, OutboxClaimRequest, AuthorityPromotionKind, VerifiedAuthorityEvidenceRecord } from "./repository";
5
+ export declare function validateMutationContext(context: MutationContext): void;
6
+ export declare function validateOutboxClaimRequest(request: OutboxClaimRequest): void;
7
+ export declare function validateOutboxAcknowledgeRequest(request: OutboxAcknowledgeRequest): void;
8
+ export declare function validateCredentialHandleEnvelope(binding: CredentialBinding, handle: CredentialHandleEnvelope): void;
9
+ export declare function buildCredentialHandleExpectedClaims(repository: Pick<AccountsRepository, "get">, binding: CredentialBinding, authority: Pick<CredentialHandleExpectedClaims, "audience" | "catalogIncarnation" | "backendClass">): Promise<CredentialHandleExpectedClaims>;
10
+ export declare function cloneEntity<K extends EntityKind>(kind: K, record: EntityMap[K]): EntityMap[K];
11
+ export declare function mutationHash<K extends EntityKind>(operation: "insert" | "replace", kind: K, record: EntityMap[K], context: MutationContext, expectedRevision?: Counter): string;
12
+ export declare function isAuthorityPromotion<K extends EntityKind>(kind: K, previous: EntityMap[K], next: EntityMap[K]): boolean;
13
+ export declare function validateVerifiedAuthorityEvidence(kind: AuthorityPromotionKind, aggregateId: string, expectedRevision: Counter, evidence: readonly VerifiedAuthorityEvidenceRecord[]): readonly VerifiedAuthorityEvidenceRecord[];
14
+ export declare function authorityPromotionHash<K extends AuthorityPromotionKind>(kind: K, record: EntityMap[K], expectedRevision: Counter, evidence: readonly VerifiedAuthorityEvidenceRecord[], context: MutationContext): string;
15
+ export declare function authorityEvidenceInsertHash(record: EntityMap["capacity_pool"], evidence: VerifiedAuthorityEvidenceRecord, context: MutationContext): string;
16
+ export declare function credentialBindingInsertHash(record: CredentialBinding, handle: CredentialHandleEnvelope, context: MutationContext): string;
17
+ export declare function idempotencyScope(operation: "insert" | "replace", kind: EntityKind, context: MutationContext): string;
18
+ export declare function assertReplacement<K extends EntityKind>(kind: K, previous: EntityMap[K], next: EntityMap[K], expectedRevision: Counter): void;
@@ -0,0 +1,11 @@
1
+ export declare const SQLITE_SCHEMA_VERSION = 2;
2
+ export declare const SQLITE_MIGRATION_V1 = "\nCREATE TABLE provider_accounts (\n id TEXT PRIMARY KEY,\n provider_key TEXT NOT NULL,\n owner_ref TEXT NOT NULL,\n provider_subject_ref TEXT,\n status TEXT NOT NULL CHECK (status IN ('pending','active','suspended','revoked')),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n payload_json TEXT NOT NULL\n);\nCREATE UNIQUE INDEX provider_accounts_active_subject\n ON provider_accounts(provider_key, provider_subject_ref)\n WHERE provider_subject_ref IS NOT NULL AND status <> 'pending';\n\nCREATE TABLE provider_subject_claims (\n provider_key TEXT NOT NULL,\n provider_subject_ref TEXT NOT NULL,\n owner_ref TEXT NOT NULL,\n provider_account_id TEXT NOT NULL REFERENCES provider_accounts(id) ON DELETE RESTRICT,\n claimed_at TEXT NOT NULL,\n PRIMARY KEY (provider_key, provider_subject_ref),\n UNIQUE (provider_account_id)\n);\n\nCREATE TABLE entitlements (\n id TEXT PRIMARY KEY,\n account_id TEXT NOT NULL REFERENCES provider_accounts(id) ON DELETE RESTRICT,\n status TEXT NOT NULL CHECK (status IN ('pending','active','paused','expired','revoked')),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n payload_json TEXT NOT NULL\n);\n\nCREATE TABLE capacity_pools (\n id TEXT PRIMARY KEY,\n account_id TEXT NOT NULL REFERENCES provider_accounts(id) ON DELETE RESTRICT,\n provider_key TEXT NOT NULL,\n capacity_domain_ref TEXT NOT NULL,\n serialization_key TEXT NOT NULL UNIQUE,\n status TEXT NOT NULL CHECK (status IN ('pending','active','draining','denied','retired')),\n deny_state TEXT NOT NULL CHECK (deny_state IN ('allowed','denied')),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n capacity_generation INTEGER NOT NULL CHECK (capacity_generation >= 0),\n deny_generation INTEGER NOT NULL CHECK (deny_generation >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n payload_json TEXT NOT NULL\n);\nCREATE UNIQUE INDEX capacity_pools_provider_domain\n ON capacity_pools(provider_key, capacity_domain_ref);\n\nCREATE TABLE capacity_domain_claims (\n provider_key TEXT NOT NULL,\n capacity_domain_ref TEXT NOT NULL,\n serialization_key TEXT NOT NULL UNIQUE,\n owner_ref TEXT NOT NULL,\n capacity_pool_id TEXT NOT NULL REFERENCES capacity_pools(id) ON DELETE RESTRICT,\n claimed_at TEXT NOT NULL,\n PRIMARY KEY (provider_key, capacity_domain_ref),\n UNIQUE (capacity_pool_id)\n);\n\nCREATE TABLE access_methods (\n id TEXT PRIMARY KEY,\n entitlement_id TEXT NOT NULL REFERENCES entitlements(id) ON DELETE RESTRICT,\n capacity_pool_id TEXT NOT NULL REFERENCES capacity_pools(id) ON DELETE RESTRICT,\n access_transport TEXT NOT NULL CHECK (access_transport IN ('native_session','api_key','workload_identity')),\n status TEXT NOT NULL CHECK (status IN ('draft','ready','draining','disabled','retired')),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n payload_json TEXT NOT NULL\n);\n\nCREATE TABLE auth_capsules (\n id TEXT PRIMARY KEY,\n access_method_id TEXT NOT NULL REFERENCES access_methods(id) ON DELETE RESTRICT,\n capacity_pool_id TEXT NOT NULL REFERENCES capacity_pools(id) ON DELETE RESTRICT,\n owner_ref TEXT NOT NULL,\n placement_ref TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('unprovisioned','bootstrapping','ready','degraded','revoked')),\n auth_generation INTEGER NOT NULL CHECK (auth_generation >= 0),\n auth_state_revision INTEGER NOT NULL CHECK (auth_state_revision >= 0),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n payload_json TEXT NOT NULL\n);\nCREATE UNIQUE INDEX auth_capsules_one_live_per_pool\n ON auth_capsules(capacity_pool_id)\n WHERE status <> 'revoked';\n\nCREATE TABLE credential_family_claims (\n credential_family_id TEXT PRIMARY KEY,\n capacity_pool_id TEXT NOT NULL REFERENCES capacity_pools(id) ON DELETE RESTRICT,\n owner_ref TEXT NOT NULL,\n purpose TEXT NOT NULL CHECK (purpose IN ('provider_session','api_key','workload_identity')),\n resolver TEXT NOT NULL CHECK (resolver IN ('brokered_secret','workload_identity','capsule_local_native')),\n claimed_at TEXT NOT NULL\n);\n\nCREATE TABLE credential_bindings (\n id TEXT PRIMARY KEY,\n access_method_id TEXT NOT NULL REFERENCES access_methods(id) ON DELETE RESTRICT,\n capacity_pool_id TEXT NOT NULL REFERENCES capacity_pools(id) ON DELETE RESTRICT,\n auth_capsule_id TEXT REFERENCES auth_capsules(id) ON DELETE RESTRICT,\n credential_family_id TEXT NOT NULL,\n resolver TEXT NOT NULL CHECK (resolver IN ('brokered_secret','workload_identity','capsule_local_native')),\n purpose TEXT NOT NULL CHECK (purpose IN ('provider_session','api_key','workload_identity')),\n status TEXT NOT NULL CHECK (status IN ('pending','active','retiring','revoked')),\n credential_generation INTEGER NOT NULL CHECK (credential_generation >= 0),\n auth_state_revision INTEGER CHECK (auth_state_revision IS NULL OR auth_state_revision >= 0),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n CHECK (\n (resolver = 'capsule_local_native' AND purpose = 'provider_session' AND auth_capsule_id IS NOT NULL AND auth_state_revision IS NOT NULL)\n OR (resolver = 'brokered_secret' AND purpose = 'api_key' AND auth_capsule_id IS NULL AND auth_state_revision IS NULL)\n OR (resolver = 'workload_identity' AND purpose = 'workload_identity' AND auth_capsule_id IS NULL AND auth_state_revision IS NULL)\n )\n);\nCREATE UNIQUE INDEX credential_bindings_family_generation\n ON credential_bindings(credential_family_id, credential_generation);\nCREATE UNIQUE INDEX credential_bindings_one_active_native\n ON credential_bindings(capacity_pool_id, purpose)\n WHERE resolver = 'capsule_local_native' AND status = 'active';\n\nCREATE TABLE account_events (\n id TEXT PRIMARY KEY,\n aggregate_kind TEXT NOT NULL CHECK (aggregate_kind IN ('account','entitlement','capacity_pool','access_method','auth_capsule','credential_binding')),\n aggregate_id TEXT NOT NULL,\n aggregate_revision INTEGER NOT NULL CHECK (aggregate_revision >= 0),\n actor_ref TEXT NOT NULL,\n reason_code TEXT NOT NULL,\n occurred_at TEXT NOT NULL\n);\n\nCREATE TABLE idempotency_records (\n scope TEXT PRIMARY KEY,\n request_hash TEXT NOT NULL,\n aggregate_kind TEXT NOT NULL,\n aggregate_id TEXT NOT NULL,\n event_id TEXT NOT NULL REFERENCES account_events(id) ON DELETE RESTRICT,\n response_json TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n";
3
+ export declare const SQLITE_MIGRATION_V1_CHECKSUM: string;
4
+ export declare const SQLITE_MIGRATION_V2 = "\nALTER TABLE access_methods RENAME TO account_lanes;\n\nCREATE TABLE accounts_installation (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n deployment_mode TEXT NOT NULL CHECK (deployment_mode IN ('local','self_hosted')),\n identity_realm TEXT NOT NULL,\n organization_ref TEXT NOT NULL,\n schema_version TEXT NOT NULL,\n build_digest TEXT NOT NULL,\n configuration_attestation_digest TEXT NOT NULL,\n catalog_incarnation TEXT NOT NULL UNIQUE,\n recovery_frontier_sequence INTEGER NOT NULL CHECK (recovery_frontier_sequence >= 0),\n recovery_frontier_hash TEXT NOT NULL,\n recovery_frontier_signature_digest TEXT NOT NULL,\n database_frontier_sequence INTEGER NOT NULL CHECK (database_frontier_sequence >= 0),\n database_frontier_hash TEXT NOT NULL,\n database_frontier_signature_digest TEXT NOT NULL,\n recovery_hold INTEGER NOT NULL CHECK (recovery_hold IN (0,1)),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nALTER TABLE credential_bindings ADD COLUMN terminal_kind TEXT\n CHECK (terminal_kind IS NULL OR terminal_kind IN ('retired_handle_generation','revocation_barrier'));\nALTER TABLE credential_bindings ADD COLUMN credential_handle_audit_digest TEXT;\nALTER TABLE credential_bindings ADD COLUMN last_usable_credential_generation INTEGER\n CHECK (last_usable_credential_generation IS NULL OR last_usable_credential_generation >= 0);\nALTER TABLE credential_bindings ADD COLUMN revocation_barrier_receipt_digest TEXT;\nALTER TABLE credential_bindings ADD COLUMN revoked_at TEXT;\n\nCREATE TRIGGER credential_bindings_terminal_shape_insert\nBEFORE INSERT ON credential_bindings BEGIN\n SELECT CASE\n WHEN NEW.status <> 'revoked' AND (\n NEW.terminal_kind IS NOT NULL OR NEW.credential_handle_audit_digest IS NOT NULL OR\n NEW.last_usable_credential_generation IS NOT NULL OR\n NEW.revocation_barrier_receipt_digest IS NOT NULL OR NEW.revoked_at IS NOT NULL\n ) THEN RAISE(ABORT, 'credential terminal fields on nonterminal row')\n WHEN NEW.status = 'revoked' AND NEW.terminal_kind = 'retired_handle_generation' AND (\n NEW.credential_handle_audit_digest IS NULL OR NEW.last_usable_credential_generation IS NOT NULL OR\n NEW.revocation_barrier_receipt_digest IS NULL OR NEW.revoked_at IS NULL\n ) THEN RAISE(ABORT, 'invalid retired handle terminal row')\n WHEN NEW.status = 'revoked' AND NEW.terminal_kind = 'revocation_barrier' AND (\n NEW.credential_handle_audit_digest IS NOT NULL OR NEW.last_usable_credential_generation IS NULL OR\n NEW.revocation_barrier_receipt_digest IS NULL OR NEW.revoked_at IS NULL\n ) THEN RAISE(ABORT, 'invalid revocation barrier row')\n WHEN NEW.status = 'revoked' AND NEW.terminal_kind IS NULL\n THEN RAISE(ABORT, 'missing credential terminal kind')\n END;\nEND;\n\nCREATE TRIGGER credential_bindings_terminal_shape_update\nBEFORE UPDATE ON credential_bindings BEGIN\n SELECT CASE\n WHEN NEW.status <> 'revoked' AND (\n NEW.terminal_kind IS NOT NULL OR NEW.credential_handle_audit_digest IS NOT NULL OR\n NEW.last_usable_credential_generation IS NOT NULL OR\n NEW.revocation_barrier_receipt_digest IS NOT NULL OR NEW.revoked_at IS NOT NULL\n ) THEN RAISE(ABORT, 'credential terminal fields on nonterminal row')\n WHEN NEW.status = 'revoked' AND NEW.terminal_kind = 'retired_handle_generation' AND (\n NEW.credential_handle_audit_digest IS NULL OR NEW.last_usable_credential_generation IS NOT NULL OR\n NEW.revocation_barrier_receipt_digest IS NULL OR NEW.revoked_at IS NULL\n ) THEN RAISE(ABORT, 'invalid retired handle terminal row')\n WHEN NEW.status = 'revoked' AND NEW.terminal_kind = 'revocation_barrier' AND (\n NEW.credential_handle_audit_digest IS NOT NULL OR NEW.last_usable_credential_generation IS NULL OR\n NEW.revocation_barrier_receipt_digest IS NULL OR NEW.revoked_at IS NULL\n ) THEN RAISE(ABORT, 'invalid revocation barrier row')\n WHEN NEW.status = 'revoked' AND NEW.terminal_kind IS NULL\n THEN RAISE(ABORT, 'missing credential terminal kind')\n END;\nEND;\n\nCREATE TABLE credential_binding_handles (\n binding_id TEXT PRIMARY KEY REFERENCES credential_bindings(id) ON DELETE RESTRICT,\n opaque_handle TEXT NOT NULL CHECK (length(opaque_handle) BETWEEN 64 AND 1024),\n issuer_ref TEXT NOT NULL,\n audience TEXT NOT NULL CHECK (audience IN ('accounts-local','accounts-self-hosted')),\n catalog_incarnation TEXT NOT NULL,\n backend_class TEXT NOT NULL CHECK (backend_class IN ('secrets_broker','workload_identity_broker','capsule_protected_state')),\n audit_digest TEXT NOT NULL,\n issued_at TEXT NOT NULL,\n expires_at TEXT\n);\nCREATE TRIGGER credential_binding_handles_nonterminal\nBEFORE INSERT ON credential_binding_handles BEGIN\n SELECT CASE WHEN (SELECT status FROM credential_bindings WHERE id = NEW.binding_id) = 'revoked'\n THEN RAISE(ABORT, 'revoked binding cannot retain a handle') END;\nEND;\nCREATE TRIGGER credential_bindings_revoke_removes_handle\nBEFORE UPDATE OF status ON credential_bindings\nWHEN NEW.status = 'revoked' AND EXISTS (\n SELECT 1 FROM credential_binding_handles WHERE binding_id = NEW.id\n)\nBEGIN\n SELECT RAISE(ABORT, 'credential handle must be removed before terminal update');\nEND;\n\nCREATE TABLE credential_operations (\n id TEXT PRIMARY KEY,\n kind TEXT NOT NULL CHECK (kind IN ('refresh','reauthentication','rotation','revocation')),\n source_binding_id TEXT REFERENCES credential_bindings(id) ON DELETE RESTRICT,\n target_binding_id TEXT REFERENCES credential_bindings(id) ON DELETE RESTRICT,\n credential_family_id TEXT NOT NULL,\n capacity_pool_id TEXT NOT NULL REFERENCES capacity_pools(id) ON DELETE RESTRICT,\n serialization_key TEXT NOT NULL,\n expected_source_generation INTEGER NOT NULL CHECK (expected_source_generation >= 0),\n expected_auth_state_revision INTEGER CHECK (expected_auth_state_revision IS NULL OR expected_auth_state_revision >= 0),\n proposed_target_generation INTEGER NOT NULL CHECK (proposed_target_generation >= 0),\n proposed_auth_state_revision INTEGER CHECK (proposed_auth_state_revision IS NULL OR proposed_auth_state_revision >= 0),\n state TEXT NOT NULL CHECK (state IN ('requested','quiescing','applying','verifying','completed','failed_before_dispatch','failed','quarantined')),\n idempotency_request_hash TEXT NOT NULL,\n barrier_receipt_digest TEXT,\n completion_receipt_digest TEXT,\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\nCREATE UNIQUE INDEX credential_operations_one_active_family_domain\n ON credential_operations(credential_family_id, serialization_key)\n WHERE state IN ('requested','quiescing','applying','verifying','failed_before_dispatch','failed');\n\nCREATE TABLE import_candidates (\n id TEXT PRIMARY KEY,\n checksum TEXT NOT NULL,\n redacted_metadata_json TEXT NOT NULL,\n state TEXT NOT NULL CHECK (state IN ('pending','confirmed','cancelled','rejected')),\n revision INTEGER NOT NULL CHECK (revision >= 0),\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\n\nCREATE TABLE evidence_records (\n id TEXT PRIMARY KEY,\n evidence_type TEXT NOT NULL,\n aggregate_kind TEXT NOT NULL CHECK (aggregate_kind IN ('provider_account','capacity_pool','entitlement','account_lane')),\n aggregate_id TEXT NOT NULL,\n aggregate_revision INTEGER NOT NULL CHECK (aggregate_revision >= 0),\n evidence_generation INTEGER NOT NULL CHECK (evidence_generation > 0),\n nonce TEXT NOT NULL UNIQUE,\n issuer_ref TEXT NOT NULL,\n issuer_class TEXT NOT NULL CHECK (issuer_class IN ('provider_ownership_verifier','provider_capacity_verifier','execution_policy_authority','terms_authority','adapter_health_reporter')),\n issuer_incarnation TEXT NOT NULL,\n audience TEXT NOT NULL,\n identity_realm TEXT NOT NULL,\n key_id TEXT NOT NULL,\n subject_ref TEXT NOT NULL,\n payload_digest TEXT NOT NULL,\n envelope_digest TEXT NOT NULL UNIQUE,\n envelope_json TEXT NOT NULL,\n issued_at TEXT NOT NULL,\n expires_at TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\nCREATE INDEX evidence_records_lookup\n ON evidence_records(aggregate_kind, aggregate_id, aggregate_revision, evidence_type);\n\nCREATE TABLE recovery_ledger_receipts (\n sequence INTEGER PRIMARY KEY CHECK (sequence >= 0),\n frontier_hash TEXT NOT NULL UNIQUE,\n frontier_signature_digest TEXT NOT NULL,\n catalog_incarnation TEXT NOT NULL,\n receipt_digest TEXT NOT NULL UNIQUE,\n entry_kind TEXT NOT NULL,\n aggregate_id TEXT,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE slot_eligibility_audit (\n id TEXT PRIMARY KEY,\n access_method_id TEXT NOT NULL REFERENCES account_lanes(id) ON DELETE RESTRICT,\n decision TEXT NOT NULL CHECK (decision IN ('eligible','ineligible')),\n reason_codes_json TEXT NOT NULL,\n request_digest TEXT NOT NULL,\n record_revision_digest TEXT NOT NULL,\n recovery_frontier_sequence INTEGER NOT NULL CHECK (recovery_frontier_sequence >= 0),\n recovery_frontier_hash TEXT NOT NULL,\n created_at TEXT NOT NULL\n);\n\nCREATE TABLE outbox (\n id TEXT PRIMARY KEY,\n topic TEXT NOT NULL CHECK (topic IN ('accounts.aggregate.changed','accounts.capsule.cleanup.requested')),\n aggregate_kind TEXT NOT NULL,\n aggregate_id TEXT NOT NULL,\n event_id TEXT REFERENCES account_events(id) ON DELETE RESTRICT,\n payload_digest TEXT NOT NULL,\n payload_json TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('pending','in_flight','delivered','dead_letter')),\n attempt_count INTEGER NOT NULL CHECK (attempt_count >= 0),\n claim_owner_ref TEXT,\n claim_expires_at TEXT,\n created_at TEXT NOT NULL\n);\nCREATE INDEX outbox_pending_order ON outbox(status, created_at, id);\n";
5
+ export declare const SQLITE_MIGRATION_V2_CHECKSUM: string;
6
+ export declare const SQLITE_MIGRATION_CHECKSUM: string;
7
+ export declare const SQLITE_MIGRATIONS: readonly {
8
+ version: number;
9
+ sql: string;
10
+ checksum: string;
11
+ }[];
@@ -0,0 +1,51 @@
1
+ import { type Counter } from "../domain/counter";
2
+ import type { CredentialBinding, CredentialOperation, EntityKind, EntityMap } from "../domain/models";
3
+ import type { AccountEvent, AccountsRepository, MutationContext, MutationResult, RepositoryDoctor, EligibilitySnapshot, CredentialHandleEnvelope, CredentialHandleVerifier, CredentialResolutionGrant, CredentialResolutionTransport, CredentialUseAuthorizer, NativeRevocationRequest, NativeRevocationResult, OutboxRecord, OutboxAcknowledgeRequest, OutboxClaimRequest, RecoveryLedger, ResolvedCredentialHandle, AuthorityPromotionKind, VerifiedAuthorityEvidenceRecord } from "./repository";
4
+ export declare class SQLiteAccountsRepository implements AccountsRepository {
5
+ readonly filename: string;
6
+ private readonly database;
7
+ private readonly credentialVerifier;
8
+ private readonly recoveryLedger;
9
+ private readonly credentialUseAuthorizer;
10
+ private readonly configuredCatalogIncarnation;
11
+ private closed;
12
+ constructor(filename: string, options?: {
13
+ readonly credentialVerifier?: CredentialHandleVerifier;
14
+ readonly recoveryLedger?: RecoveryLedger;
15
+ readonly catalogIncarnation?: string;
16
+ readonly credentialUseAuthorizer?: CredentialUseAuthorizer;
17
+ });
18
+ get<K extends EntityKind>(kind: K, id: EntityMap[K]["id"]): Promise<EntityMap[K] | undefined>;
19
+ list<K extends EntityKind>(kind: K): Promise<readonly EntityMap[K][]>;
20
+ readEligibilitySnapshot(accessMethodId: EntityMap["access_method"]["id"]): Promise<EligibilitySnapshot>;
21
+ insert<K extends EntityKind>(kind: K, input: EntityMap[K], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
22
+ insertCapacityPoolWithAuthorityEvidence(input: EntityMap["capacity_pool"], inputEvidence: VerifiedAuthorityEvidenceRecord, context: MutationContext): Promise<MutationResult<EntityMap["capacity_pool"]>>;
23
+ insertCredentialBinding(input: CredentialBinding, inputHandle: CredentialHandleEnvelope, context: MutationContext): Promise<MutationResult<CredentialBinding>>;
24
+ resolveCredentialHandle(bindingId: CredentialBinding["id"], grant: CredentialResolutionGrant, transport: CredentialResolutionTransport): Promise<ResolvedCredentialHandle>;
25
+ replace<K extends EntityKind>(kind: K, input: EntityMap[K], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
26
+ promoteWithAuthorityEvidence<K extends AuthorityPromotionKind>(kind: K, input: EntityMap[K], expectedRevision: Counter, inputEvidence: readonly VerifiedAuthorityEvidenceRecord[], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
27
+ events(): Promise<readonly AccountEvent[]>;
28
+ revokeNativeGeneration(request: NativeRevocationRequest): Promise<NativeRevocationResult>;
29
+ credentialOperations(): Promise<readonly CredentialOperation[]>;
30
+ outbox(): Promise<readonly OutboxRecord[]>;
31
+ claimOutbox(request: OutboxClaimRequest): Promise<readonly OutboxRecord[]>;
32
+ acknowledgeOutbox(request: OutboxAcknowledgeRequest): Promise<OutboxRecord>;
33
+ findReplacementReplay<K extends EntityKind>(kind: K, id: EntityMap[K]["id"], to: EntityMap[K]["status"], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]> | undefined>;
34
+ doctor(): Promise<RepositoryDoctor>;
35
+ close(): Promise<void>;
36
+ private installationCatalogIncarnation;
37
+ private readRecoverySnapshot;
38
+ private appendRecovery;
39
+ private migrate;
40
+ private readOne;
41
+ private insertRecord;
42
+ private updateRecord;
43
+ private recordMutation;
44
+ private appendEventAndOutbox;
45
+ private appendCleanupOutbox;
46
+ private insertOperation;
47
+ private readNativeRevocationResult;
48
+ private replay;
49
+ private secureFiles;
50
+ private assertOpen;
51
+ }
@@ -0,0 +1,2 @@
1
+ export declare const PACKAGE_VERSION: "0.1.0";
2
+ export declare const ACCOUNTS_V1_CONTRACT_SHA256: "0d2b45c286f56452312b251b7622e009c486e2fe71fe8f2a5a59c01472eb8b2a";
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@hasna/capacity",
3
+ "version": "0.1.0",
4
+ "description": "Fail-closed provider account capacity metadata for local and self-hosted Hasna deployments",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/hasna/capacity.git"
10
+ },
11
+ "sideEffects": false,
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ },
17
+ "./capacity": {
18
+ "types": "./dist/index.d.ts",
19
+ "import": "./dist/index.js"
20
+ }
21
+ },
22
+ "bin": {
23
+ "capacity": "./dist/cli.js"
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "scripts": {
31
+ "build": "rm -rf dist && bun run build:js && bun run build:types",
32
+ "build:js": "bun build src/index.ts --outdir dist --target bun --format esm && bun build src/cli.ts --outfile dist/cli.js --target bun --format esm",
33
+ "build:types": "tsc -p tsconfig.build.json",
34
+ "test": "bun test",
35
+ "test:unit": "bun test test/unit",
36
+ "test:storage": "bun test test/storage",
37
+ "typecheck": "tsc --noEmit"
38
+ },
39
+ "devDependencies": {
40
+ "@types/bun": "1.3.5",
41
+ "typescript": "5.9.3"
42
+ },
43
+ "publishConfig": {
44
+ "access": "public"
45
+ },
46
+ "engines": {
47
+ "bun": ">=1.3.0"
48
+ }
49
+ }