@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.
- package/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +6663 -0
- package/dist/domain/authority-evidence.d.ts +198 -0
- package/dist/domain/catalog.d.ts +65 -0
- package/dist/domain/counter.d.ts +7 -0
- package/dist/domain/eligibility.d.ts +4 -0
- package/dist/domain/ids.d.ts +47 -0
- package/dist/domain/invariants.d.ts +4 -0
- package/dist/domain/models.d.ts +300 -0
- package/dist/domain/native-subscription.d.ts +211 -0
- package/dist/domain/online-generation-receipt.d.ts +497 -0
- package/dist/domain/state.d.ts +19 -0
- package/dist/errors.d.ts +26 -0
- package/dist/http/handler.d.ts +3 -0
- package/dist/http/openapi.d.ts +1070 -0
- package/dist/http/stores.d.ts +20 -0
- package/dist/http/types.d.ts +141 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +14909 -0
- package/dist/sdk/index.d.ts +8 -0
- package/dist/sdk/local.d.ts +5 -0
- package/dist/sdk/remote.d.ts +2 -0
- package/dist/sdk/types.d.ts +107 -0
- package/dist/serialization/dto.d.ts +13 -0
- package/dist/serialization/json.d.ts +7 -0
- package/dist/storage/credential-use-authorizer.d.ts +9 -0
- package/dist/storage/credential-verifier.d.ts +13 -0
- package/dist/storage/effect-dispatch.d.ts +278 -0
- package/dist/storage/file-recovery-ledger.d.ts +66 -0
- package/dist/storage/memory.d.ts +47 -0
- package/dist/storage/native-revocation.d.ts +10 -0
- package/dist/storage/postgres-config.d.ts +25 -0
- package/dist/storage/postgres-migrations.d.ts +10 -0
- package/dist/storage/postgres-migrator.d.ts +12 -0
- package/dist/storage/postgres.d.ts +90 -0
- package/dist/storage/recovery.d.ts +11 -0
- package/dist/storage/repository.d.ts +310 -0
- package/dist/storage/shared.d.ts +18 -0
- package/dist/storage/sqlite-migrations.d.ts +11 -0
- package/dist/storage/sqlite.d.ts +51 -0
- package/dist/version.d.ts +2 -0
- package/package.json +49 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AccountsCapacity, AccountsDeployment } from "./types";
|
|
2
|
+
export type { AccountLanesApi, AccountsAuthProvider, AccountsCapacity, AccountsDeployment, AuthCapsulesApi, BootstrapIntentInput, CallOptions, CapacityQueryApi, CreateAccountLaneInput, CreateEntitlementInput, CreateProviderAccountInput, EntitlementsApi, ListOptions, LocalRecoveryConfiguration, MutationOptions, Page, ProviderAccountsApi, ProviderAccountView, ReadonlyCapacityPoolsApi, ReadonlyCredentialBindingsApi, RevisionMutationOptions, } from "./types";
|
|
3
|
+
export { createLocalAccountsCapacityFromCatalog } from "./local";
|
|
4
|
+
/**
|
|
5
|
+
* Deployment choice is explicit and immutable. A self-hosted error is returned
|
|
6
|
+
* to the caller and never falls back to SQLite.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createAccountsCapacity(config: AccountsDeployment): AccountsCapacity;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AccountsCatalog } from "../domain/catalog";
|
|
2
|
+
import type { AccountsCapacity, LocalRecoveryConfiguration } from "./types";
|
|
3
|
+
export declare function createLocalAccountsCapacity(actorRef: string, sqlitePath?: string, recovery?: LocalRecoveryConfiguration): AccountsCapacity;
|
|
4
|
+
/** Integration seam for a catalog configured with the package-owned persistent recovery ledger. */
|
|
5
|
+
export declare function createLocalAccountsCapacityFromCatalog(catalog: AccountsCatalog, actorRef: string): AccountsCapacity;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { Account, AccessMethod, AuthCapsule, CapacityPool, CredentialBindingMetadata, EligibilityRequest, Entitlement, FundingKind, SlotEligibilityMetadata } from "../domain/models";
|
|
2
|
+
import type { Counter } from "../domain/counter";
|
|
3
|
+
import type { AccountId, AccessMethodId, AuthCapsuleId, CapacityPoolId, CredentialBindingId, EntitlementId } from "../domain/ids";
|
|
4
|
+
import type { BootstrapIntent } from "../http/types";
|
|
5
|
+
export interface AccountsAuthProvider {
|
|
6
|
+
/** Adds a separately audienced capacity authorization header. */
|
|
7
|
+
authorize(headers: Headers, signal?: AbortSignal): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface LocalRecoveryConfiguration {
|
|
10
|
+
readonly ledgerPath: string;
|
|
11
|
+
readonly catalogIncarnation: string;
|
|
12
|
+
readonly signingKey: Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
export type AccountsDeployment = {
|
|
15
|
+
readonly mode: "local";
|
|
16
|
+
readonly sqlitePath?: string;
|
|
17
|
+
readonly actorRef: string;
|
|
18
|
+
readonly recovery?: LocalRecoveryConfiguration;
|
|
19
|
+
} | {
|
|
20
|
+
readonly mode: "self_hosted";
|
|
21
|
+
readonly baseUrl: string;
|
|
22
|
+
readonly authProvider: AccountsAuthProvider;
|
|
23
|
+
};
|
|
24
|
+
export interface CallOptions {
|
|
25
|
+
readonly signal?: AbortSignal;
|
|
26
|
+
}
|
|
27
|
+
export interface ListOptions extends CallOptions {
|
|
28
|
+
readonly cursor?: string;
|
|
29
|
+
readonly limit?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface MutationOptions extends CallOptions {
|
|
32
|
+
readonly idempotencyKey: string;
|
|
33
|
+
}
|
|
34
|
+
export interface RevisionMutationOptions extends MutationOptions {
|
|
35
|
+
readonly expectedRevision: Counter;
|
|
36
|
+
}
|
|
37
|
+
export interface Page<T> {
|
|
38
|
+
readonly records: readonly T[];
|
|
39
|
+
readonly nextCursor: string | null;
|
|
40
|
+
}
|
|
41
|
+
/** Normal readers never receive provider subject values or candidate fingerprints. */
|
|
42
|
+
export type ProviderAccountView = Omit<Account, "providerSubjectRef" | "providerSubjectCandidateRef"> & {
|
|
43
|
+
readonly providerSubjectRefRedacted?: true;
|
|
44
|
+
};
|
|
45
|
+
export interface CreateProviderAccountInput {
|
|
46
|
+
readonly providerKey: string;
|
|
47
|
+
readonly ownerRef: string;
|
|
48
|
+
readonly displayLabel: string;
|
|
49
|
+
readonly providerSubjectCandidateRef?: string;
|
|
50
|
+
readonly providerDisplayHint?: string;
|
|
51
|
+
}
|
|
52
|
+
export interface CreateEntitlementInput {
|
|
53
|
+
readonly providerAccountId: AccountId;
|
|
54
|
+
readonly fundingKind: FundingKind;
|
|
55
|
+
}
|
|
56
|
+
export interface CreateAccountLaneInput {
|
|
57
|
+
readonly entitlementId: EntitlementId;
|
|
58
|
+
readonly capacityPoolId: CapacityPoolId;
|
|
59
|
+
readonly adapterKey: string;
|
|
60
|
+
readonly adapterVersion: string;
|
|
61
|
+
readonly accessTransport: AccessMethod["accessTransport"];
|
|
62
|
+
}
|
|
63
|
+
export interface BootstrapIntentInput {
|
|
64
|
+
readonly reasonCode: string;
|
|
65
|
+
}
|
|
66
|
+
export interface ProviderAccountsApi {
|
|
67
|
+
list(options?: ListOptions): Promise<Page<ProviderAccountView>>;
|
|
68
|
+
get(id: AccountId, options?: CallOptions): Promise<ProviderAccountView>;
|
|
69
|
+
create(input: CreateProviderAccountInput, options: MutationOptions): Promise<ProviderAccountView>;
|
|
70
|
+
}
|
|
71
|
+
export interface EntitlementsApi {
|
|
72
|
+
list(options?: ListOptions): Promise<Page<Entitlement>>;
|
|
73
|
+
get(id: EntitlementId, options?: CallOptions): Promise<Entitlement>;
|
|
74
|
+
create(input: CreateEntitlementInput, options: MutationOptions): Promise<Entitlement>;
|
|
75
|
+
}
|
|
76
|
+
export interface ReadonlyCapacityPoolsApi {
|
|
77
|
+
list(options?: ListOptions): Promise<Page<CapacityPool>>;
|
|
78
|
+
get(id: CapacityPoolId, options?: CallOptions): Promise<CapacityPool>;
|
|
79
|
+
}
|
|
80
|
+
export interface AccountLanesApi {
|
|
81
|
+
list(options?: ListOptions): Promise<Page<AccessMethod>>;
|
|
82
|
+
get(id: AccessMethodId, options?: CallOptions): Promise<AccessMethod>;
|
|
83
|
+
create(input: CreateAccountLaneInput, options: MutationOptions): Promise<AccessMethod>;
|
|
84
|
+
}
|
|
85
|
+
export interface AuthCapsulesApi {
|
|
86
|
+
list(options?: ListOptions): Promise<Page<AuthCapsule>>;
|
|
87
|
+
get(id: AuthCapsuleId, options?: CallOptions): Promise<AuthCapsule>;
|
|
88
|
+
createBootstrapIntent(id: AuthCapsuleId, input: BootstrapIntentInput, options: RevisionMutationOptions): Promise<BootstrapIntent>;
|
|
89
|
+
getBootstrapIntent(id: AuthCapsuleId, intentId: string, options?: CallOptions): Promise<BootstrapIntent>;
|
|
90
|
+
}
|
|
91
|
+
export interface ReadonlyCredentialBindingsApi {
|
|
92
|
+
list(options?: ListOptions): Promise<Page<CredentialBindingMetadata>>;
|
|
93
|
+
get(id: CredentialBindingId, options?: CallOptions): Promise<CredentialBindingMetadata>;
|
|
94
|
+
}
|
|
95
|
+
export interface CapacityQueryApi {
|
|
96
|
+
query(request: EligibilityRequest, options?: CallOptions): Promise<SlotEligibilityMetadata>;
|
|
97
|
+
}
|
|
98
|
+
export interface AccountsCapacity {
|
|
99
|
+
readonly providerAccounts: ProviderAccountsApi;
|
|
100
|
+
readonly entitlements: EntitlementsApi;
|
|
101
|
+
readonly capacityPools: ReadonlyCapacityPoolsApi;
|
|
102
|
+
readonly lanes: AccountLanesApi;
|
|
103
|
+
readonly capsules: AuthCapsulesApi;
|
|
104
|
+
readonly credentialBindings: ReadonlyCredentialBindingsApi;
|
|
105
|
+
readonly capacity: CapacityQueryApi;
|
|
106
|
+
close(options?: CallOptions): Promise<void>;
|
|
107
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ACCOUNTS_CAPACITY_SCHEMA_VERSION, type EntityKind, type EntityMap, type EligibilityRequest, type SlotEligibilityMetadata } from "../domain/models";
|
|
2
|
+
export declare function validateEntity<K extends EntityKind>(kind: K, input: unknown): EntityMap[K];
|
|
3
|
+
export declare function validateEligibilityRequest(input: unknown): EligibilityRequest;
|
|
4
|
+
export interface RecordEnvelope<K extends EntityKind = EntityKind> {
|
|
5
|
+
readonly schemaVersion: typeof ACCOUNTS_CAPACITY_SCHEMA_VERSION;
|
|
6
|
+
readonly kind: K;
|
|
7
|
+
readonly data: EntityMap[K];
|
|
8
|
+
}
|
|
9
|
+
export declare function encodeRecordEnvelope<K extends EntityKind>(kind: K, data: EntityMap[K]): RecordEnvelope<K>;
|
|
10
|
+
export declare function decodeRecordEnvelope(input: unknown): RecordEnvelope;
|
|
11
|
+
export declare function serializeRecordEnvelope<K extends EntityKind>(kind: K, data: EntityMap[K]): string;
|
|
12
|
+
export declare function deserializeRecordEnvelope(source: string): RecordEnvelope;
|
|
13
|
+
export declare function validateSlotEligibility(input: unknown): SlotEligibilityMetadata;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function parseClosedJson(source: string): unknown;
|
|
2
|
+
export declare function parseClosedJsonBytes(source: Uint8Array): unknown;
|
|
3
|
+
export declare function canonicalJson(value: unknown): string;
|
|
4
|
+
export declare function canonicalSha256(value: unknown): string;
|
|
5
|
+
export declare function assertNoSensitiveFields(value: unknown, path?: string, seen?: Set<object>): void;
|
|
6
|
+
export declare function isSensitiveFieldName(key: string): boolean;
|
|
7
|
+
export declare function assertNoSecretLikeString(value: string): void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { KeyObject, type KeyLike } from "node:crypto";
|
|
2
|
+
import type { CredentialResolutionExpected, CredentialResolutionGrant, CredentialResolutionTransport, CredentialUseAuthorizer, UnsignedCredentialResolutionGrant } from "./repository";
|
|
3
|
+
export declare class Ed25519CredentialUseAuthorizer implements CredentialUseAuthorizer {
|
|
4
|
+
private readonly publicKeys;
|
|
5
|
+
constructor(issuerPublicKeys: ReadonlyMap<string, KeyObject | string | Buffer>);
|
|
6
|
+
verify(grant: CredentialResolutionGrant, expected: CredentialResolutionExpected, transport: CredentialResolutionTransport): void;
|
|
7
|
+
}
|
|
8
|
+
export declare const REJECTING_CREDENTIAL_USE_AUTHORIZER: CredentialUseAuthorizer;
|
|
9
|
+
export declare function signCredentialResolutionGrant(unsigned: UnsignedCredentialResolutionGrant, privateKey: KeyLike): CredentialResolutionGrant;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type KeyLike, KeyObject } from "node:crypto";
|
|
2
|
+
import type { CredentialHandleEnvelope, CredentialHandleExpectedClaims, CredentialHandleVerification, CredentialHandleVerifier, UnsignedCredentialHandleEnvelope } from "./repository";
|
|
3
|
+
export declare class Ed25519CredentialHandleVerifier implements CredentialHandleVerifier {
|
|
4
|
+
private readonly publicKeys;
|
|
5
|
+
private readonly auditKey;
|
|
6
|
+
constructor(input: {
|
|
7
|
+
readonly issuerPublicKeys: ReadonlyMap<string, KeyObject | string | Buffer>;
|
|
8
|
+
readonly auditKey: Uint8Array;
|
|
9
|
+
});
|
|
10
|
+
verify(envelope: CredentialHandleEnvelope, expected: CredentialHandleExpectedClaims): CredentialHandleVerification;
|
|
11
|
+
}
|
|
12
|
+
export declare const REJECTING_CREDENTIAL_HANDLE_VERIFIER: CredentialHandleVerifier;
|
|
13
|
+
export declare function signCredentialHandleEnvelope(unsigned: UnsignedCredentialHandleEnvelope, privateKey: KeyLike): CredentialHandleEnvelope;
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { type KeyObject } from "node:crypto";
|
|
2
|
+
import { type Counter } from "../domain/counter";
|
|
3
|
+
import { type SignedLogFrontier } from "./file-recovery-ledger";
|
|
4
|
+
declare const CLAIM_SCHEMA: "accounts.credential-effect-claim.v1";
|
|
5
|
+
declare const PREPARED_SCHEMA: "accounts.credential-effect-prepared.v1";
|
|
6
|
+
declare const DISPATCHED_SCHEMA: "accounts.credential-effect-dispatched.v1";
|
|
7
|
+
declare const OUTCOME_SCHEMA: "infinity.effect-journal-outcome/v1";
|
|
8
|
+
declare const OUTCOME_SCHEMA_DIGEST: "sha256:7ab380a0475ebf79d2ed925e20bcbb9303d78a56c358d09adbdce796e740bf20";
|
|
9
|
+
declare const LOOKUP_SCHEMA: "accounts.provider-effect-lookup.v1";
|
|
10
|
+
export type EffectOutcomeKind = "succeeded" | "failed_effect" | "failed_no_effect" | "reconciliation_blocked";
|
|
11
|
+
export interface EffectClaimRecord {
|
|
12
|
+
readonly schema_version: typeof CLAIM_SCHEMA;
|
|
13
|
+
readonly record_kind: "CLAIMED";
|
|
14
|
+
readonly semantic_operation_key_digest: string;
|
|
15
|
+
readonly operation_id: string;
|
|
16
|
+
readonly operation_step_id: string;
|
|
17
|
+
readonly credential_family_id: string;
|
|
18
|
+
readonly serialization_key_digest: string;
|
|
19
|
+
readonly request_digest: string;
|
|
20
|
+
readonly source_fences_digest: string;
|
|
21
|
+
readonly claimed_at: string;
|
|
22
|
+
}
|
|
23
|
+
export interface EffectPreparedRecord {
|
|
24
|
+
readonly schema_version: typeof PREPARED_SCHEMA;
|
|
25
|
+
readonly record_kind: "PREPARED";
|
|
26
|
+
readonly semantic_operation_key_digest: string;
|
|
27
|
+
readonly operation_id: string;
|
|
28
|
+
readonly operation_step_id: string;
|
|
29
|
+
readonly operation_execution_epoch: Counter;
|
|
30
|
+
readonly credential_family_id: string;
|
|
31
|
+
readonly serialization_key_digest: string;
|
|
32
|
+
readonly operation_digest: string;
|
|
33
|
+
readonly request_digest: string;
|
|
34
|
+
readonly target_digest: string;
|
|
35
|
+
readonly source_fences_digest: string;
|
|
36
|
+
readonly maintenance_fence_digest: string;
|
|
37
|
+
readonly maintenance_grant_digest: string;
|
|
38
|
+
readonly effect_endpoint_ref: string;
|
|
39
|
+
readonly provider_key: string;
|
|
40
|
+
readonly prepared_at: string;
|
|
41
|
+
readonly prior_failed_no_effect_receipt_digest?: string;
|
|
42
|
+
}
|
|
43
|
+
interface EffectDispatchedCommon {
|
|
44
|
+
readonly schema_version: typeof DISPATCHED_SCHEMA;
|
|
45
|
+
readonly record_kind: "DISPATCHED";
|
|
46
|
+
readonly outcome_schema_version: typeof OUTCOME_SCHEMA;
|
|
47
|
+
readonly outcome_schema_digest: typeof OUTCOME_SCHEMA_DIGEST;
|
|
48
|
+
readonly semantic_operation_key_digest: string;
|
|
49
|
+
readonly operation_id: string;
|
|
50
|
+
readonly operation_step_id: string;
|
|
51
|
+
readonly operation_digest: string;
|
|
52
|
+
readonly request_digest: string;
|
|
53
|
+
readonly target_digest: string;
|
|
54
|
+
readonly source_fences_digest: string;
|
|
55
|
+
readonly maintenance_fence_digest: string;
|
|
56
|
+
readonly maintenance_grant_digest: string;
|
|
57
|
+
readonly operation_execution_epoch: Counter;
|
|
58
|
+
readonly provider_key: string;
|
|
59
|
+
readonly effect_endpoint_ref: string;
|
|
60
|
+
readonly provider_idempotency_token_sha256: string;
|
|
61
|
+
readonly prepared_receipt_digest: string;
|
|
62
|
+
readonly audience: string;
|
|
63
|
+
readonly dispatched_at: string;
|
|
64
|
+
readonly signer_ref: string;
|
|
65
|
+
readonly signer_incarnation: string;
|
|
66
|
+
readonly key_id: string;
|
|
67
|
+
}
|
|
68
|
+
export interface EffectDispatchedRecord extends EffectDispatchedCommon {
|
|
69
|
+
readonly signature: string;
|
|
70
|
+
}
|
|
71
|
+
export type UnsignedEffectDispatchedRecord = EffectDispatchedCommon;
|
|
72
|
+
interface EffectOutcomeCommon {
|
|
73
|
+
readonly schema_version: typeof OUTCOME_SCHEMA;
|
|
74
|
+
readonly schema_digest: typeof OUTCOME_SCHEMA_DIGEST;
|
|
75
|
+
readonly record_kind: "OUTCOME";
|
|
76
|
+
readonly semantic_operation_key_digest: string;
|
|
77
|
+
readonly operation_id: string;
|
|
78
|
+
readonly operation_step_id: string;
|
|
79
|
+
readonly operation_digest: string;
|
|
80
|
+
readonly request_digest: string;
|
|
81
|
+
readonly target_digest: string;
|
|
82
|
+
readonly source_fences_digest: string;
|
|
83
|
+
readonly maintenance_grant_digest: string;
|
|
84
|
+
readonly maintenance_fence_digest: string;
|
|
85
|
+
readonly operation_execution_epoch: Counter;
|
|
86
|
+
readonly dispatched_receipt_digest: string;
|
|
87
|
+
readonly provider_idempotency_token_sha256: string;
|
|
88
|
+
readonly effect_endpoint_ref: string;
|
|
89
|
+
readonly effect_endpoint_incarnation: string;
|
|
90
|
+
readonly effect_endpoint_key_id: string;
|
|
91
|
+
readonly audience: string;
|
|
92
|
+
readonly observed_at: string;
|
|
93
|
+
}
|
|
94
|
+
export interface EffectSucceededOutcome extends EffectOutcomeCommon {
|
|
95
|
+
readonly outcome_kind: "succeeded";
|
|
96
|
+
readonly provider_result_receipt_digest: string;
|
|
97
|
+
readonly endpoint_signature: string;
|
|
98
|
+
}
|
|
99
|
+
export interface EffectFailedEffectOutcome extends EffectOutcomeCommon {
|
|
100
|
+
readonly outcome_kind: "failed_effect";
|
|
101
|
+
readonly provider_failure_receipt_digest: string;
|
|
102
|
+
readonly endpoint_signature: string;
|
|
103
|
+
}
|
|
104
|
+
export interface EffectFailedNoEffectOutcome extends EffectOutcomeCommon {
|
|
105
|
+
readonly outcome_kind: "failed_no_effect";
|
|
106
|
+
readonly provider_lookup_evidence_digest: string;
|
|
107
|
+
readonly endpoint_signature: string;
|
|
108
|
+
}
|
|
109
|
+
export interface EffectReconciliationBlockedOutcome extends EffectOutcomeCommon {
|
|
110
|
+
readonly outcome_kind: "reconciliation_blocked";
|
|
111
|
+
readonly reconciliation_evidence_digest: string;
|
|
112
|
+
readonly endpoint_signature: string;
|
|
113
|
+
}
|
|
114
|
+
export type EffectOutcomeRecord = EffectSucceededOutcome | EffectFailedEffectOutcome | EffectFailedNoEffectOutcome | EffectReconciliationBlockedOutcome;
|
|
115
|
+
export type UnsignedEffectOutcomeRecord = Omit<EffectSucceededOutcome, "endpoint_signature"> | Omit<EffectFailedEffectOutcome, "endpoint_signature"> | Omit<EffectFailedNoEffectOutcome, "endpoint_signature"> | Omit<EffectReconciliationBlockedOutcome, "endpoint_signature">;
|
|
116
|
+
export type EffectDispatchRecord = EffectDispatchedRecord | EffectOutcomeRecord;
|
|
117
|
+
interface ProviderLookupEvidenceCommon {
|
|
118
|
+
readonly schema_version: typeof LOOKUP_SCHEMA;
|
|
119
|
+
readonly provider_key: string;
|
|
120
|
+
readonly provider_lookup_issuer_ref: string;
|
|
121
|
+
readonly provider_lookup_issuer_incarnation: string;
|
|
122
|
+
readonly provider_lookup_key_id: string;
|
|
123
|
+
readonly audience: string;
|
|
124
|
+
readonly effect_endpoint_ref: string;
|
|
125
|
+
readonly provider_idempotency_token_sha256: string;
|
|
126
|
+
readonly semantic_operation_key_digest: string;
|
|
127
|
+
readonly operation_id: string;
|
|
128
|
+
readonly operation_step_id: string;
|
|
129
|
+
readonly operation_digest: string;
|
|
130
|
+
readonly request_digest: string;
|
|
131
|
+
readonly target_digest: string;
|
|
132
|
+
readonly source_fences_digest: string;
|
|
133
|
+
readonly maintenance_fence_digest: string;
|
|
134
|
+
readonly maintenance_grant_digest: string;
|
|
135
|
+
readonly operation_execution_epoch: Counter;
|
|
136
|
+
readonly lookup_result: "rejected_not_accepted_no_state_change";
|
|
137
|
+
readonly provider_observation_id: string;
|
|
138
|
+
readonly issued_at: string;
|
|
139
|
+
readonly expires_at: string;
|
|
140
|
+
}
|
|
141
|
+
export interface ProviderLookupEvidence extends ProviderLookupEvidenceCommon {
|
|
142
|
+
readonly provider_signature: string;
|
|
143
|
+
}
|
|
144
|
+
export type UnsignedProviderLookupEvidence = ProviderLookupEvidenceCommon;
|
|
145
|
+
export interface EffectPrepareInput {
|
|
146
|
+
readonly operation_id: string;
|
|
147
|
+
readonly operation_step_id: string;
|
|
148
|
+
readonly operation_execution_epoch: Counter;
|
|
149
|
+
readonly credential_family_id: string;
|
|
150
|
+
readonly serialization_key_digest: string;
|
|
151
|
+
readonly operation_digest: string;
|
|
152
|
+
readonly request_digest: string;
|
|
153
|
+
readonly target_digest: string;
|
|
154
|
+
readonly source_fences_digest: string;
|
|
155
|
+
readonly maintenance_fence_digest: string;
|
|
156
|
+
readonly maintenance_grant_digest: string;
|
|
157
|
+
readonly effect_endpoint_ref: string;
|
|
158
|
+
readonly provider_key: string;
|
|
159
|
+
readonly prior_failed_no_effect_receipt_digest?: string;
|
|
160
|
+
}
|
|
161
|
+
export interface EffectDispatchInput {
|
|
162
|
+
readonly operation_id: string;
|
|
163
|
+
readonly operation_step_id: string;
|
|
164
|
+
readonly operation_execution_epoch: Counter;
|
|
165
|
+
readonly prepared_receipt_digest: string;
|
|
166
|
+
}
|
|
167
|
+
interface OutcomeSigningCommonInput {
|
|
168
|
+
readonly operation_id: string;
|
|
169
|
+
readonly operation_step_id: string;
|
|
170
|
+
readonly operation_execution_epoch: Counter;
|
|
171
|
+
readonly dispatched_receipt_digest: string;
|
|
172
|
+
readonly observed_at: string;
|
|
173
|
+
}
|
|
174
|
+
export type EffectOutcomeSigningInput = (OutcomeSigningCommonInput & {
|
|
175
|
+
readonly outcome_kind: "succeeded";
|
|
176
|
+
readonly provider_result_receipt_digest: string;
|
|
177
|
+
}) | (OutcomeSigningCommonInput & {
|
|
178
|
+
readonly outcome_kind: "failed_effect";
|
|
179
|
+
readonly provider_failure_receipt_digest: string;
|
|
180
|
+
}) | (OutcomeSigningCommonInput & {
|
|
181
|
+
readonly outcome_kind: "failed_no_effect";
|
|
182
|
+
readonly provider_lookup_evidence_digest: string;
|
|
183
|
+
}) | (OutcomeSigningCommonInput & {
|
|
184
|
+
readonly outcome_kind: "reconciliation_blocked";
|
|
185
|
+
readonly reconciliation_evidence_digest: string;
|
|
186
|
+
});
|
|
187
|
+
export interface EffectJournalAppend<T> {
|
|
188
|
+
readonly record: T;
|
|
189
|
+
readonly receipt_digest: string;
|
|
190
|
+
readonly frontier: SignedLogFrontier;
|
|
191
|
+
readonly replayed: boolean;
|
|
192
|
+
}
|
|
193
|
+
export interface EffectDispatchAppend extends EffectJournalAppend<EffectDispatchedRecord> {
|
|
194
|
+
/** The raw token is returned only to the caller that may invoke the endpoint. */
|
|
195
|
+
readonly provider_idempotency_token: string;
|
|
196
|
+
/** True only for the process that durably appended the first DISPATCHED record. */
|
|
197
|
+
readonly newly_appended: boolean;
|
|
198
|
+
}
|
|
199
|
+
export type EffectDispatchState = {
|
|
200
|
+
readonly phase: "PREPARED";
|
|
201
|
+
readonly operation_execution_epoch: Counter;
|
|
202
|
+
readonly prepared: EffectJournalAppend<EffectPreparedRecord>;
|
|
203
|
+
} | {
|
|
204
|
+
readonly phase: "DISPATCHED";
|
|
205
|
+
readonly operation_execution_epoch: Counter;
|
|
206
|
+
readonly prepared: EffectJournalAppend<EffectPreparedRecord>;
|
|
207
|
+
readonly dispatched: EffectJournalAppend<EffectDispatchedRecord>;
|
|
208
|
+
} | {
|
|
209
|
+
readonly phase: "OUTCOME";
|
|
210
|
+
readonly operation_execution_epoch: Counter;
|
|
211
|
+
readonly outcome_kind: EffectOutcomeKind;
|
|
212
|
+
readonly prepared: EffectJournalAppend<EffectPreparedRecord>;
|
|
213
|
+
readonly dispatched: EffectJournalAppend<EffectDispatchedRecord>;
|
|
214
|
+
readonly outcome: EffectJournalAppend<EffectOutcomeRecord>;
|
|
215
|
+
};
|
|
216
|
+
export interface EffectDispatchSigner {
|
|
217
|
+
readonly signerRef: string;
|
|
218
|
+
readonly signerIncarnation: string;
|
|
219
|
+
readonly keyId: string;
|
|
220
|
+
readonly audience: string;
|
|
221
|
+
readonly privateKey: KeyObject;
|
|
222
|
+
}
|
|
223
|
+
export interface EffectEndpointTrust {
|
|
224
|
+
readonly incarnation: string;
|
|
225
|
+
readonly keyId: string;
|
|
226
|
+
readonly audience: string;
|
|
227
|
+
readonly publicKey: KeyObject;
|
|
228
|
+
}
|
|
229
|
+
export interface ProviderLookupTrust {
|
|
230
|
+
readonly incarnation: string;
|
|
231
|
+
readonly keyId: string;
|
|
232
|
+
readonly audience: string;
|
|
233
|
+
readonly publicKey: KeyObject;
|
|
234
|
+
}
|
|
235
|
+
export interface EffectDispatchJournalOptions {
|
|
236
|
+
readonly path: string;
|
|
237
|
+
readonly catalogIncarnation: string;
|
|
238
|
+
readonly signingKey: Uint8Array;
|
|
239
|
+
readonly dispatchSigner: EffectDispatchSigner;
|
|
240
|
+
readonly effectEndpointTrust: ReadonlyMap<string, EffectEndpointTrust>;
|
|
241
|
+
readonly providerLookupTrust: ReadonlyMap<string, ProviderLookupTrust>;
|
|
242
|
+
readonly clock?: () => Date;
|
|
243
|
+
}
|
|
244
|
+
/** Exact RFC 8785 JCS bytes signed by the Accounts effect sink. */
|
|
245
|
+
export declare function effectDispatchedSigningBytes(dispatched: UnsignedEffectDispatchedRecord): Uint8Array;
|
|
246
|
+
/** Exact RFC 8785 JCS bytes an owning effect endpoint signs. */
|
|
247
|
+
export declare function effectOutcomeSigningBytes(outcome: UnsignedEffectOutcomeRecord): Uint8Array;
|
|
248
|
+
/** Exact RFC 8785 JCS bytes a provider lookup issuer signs. */
|
|
249
|
+
export declare function providerLookupEvidenceSigningBytes(evidence: UnsignedProviderLookupEvidence): Uint8Array;
|
|
250
|
+
export declare class EffectDispatchJournal {
|
|
251
|
+
private readonly claimLog;
|
|
252
|
+
private readonly preparedLog;
|
|
253
|
+
private readonly effectLog;
|
|
254
|
+
private readonly catalogIncarnation;
|
|
255
|
+
private readonly dispatchSigner;
|
|
256
|
+
private readonly endpointTrust;
|
|
257
|
+
private readonly lookupTrust;
|
|
258
|
+
private readonly clock;
|
|
259
|
+
constructor(options: EffectDispatchJournalOptions);
|
|
260
|
+
readState(operationId: string, operationStepId: string): EffectDispatchState | undefined;
|
|
261
|
+
prepare(input: EffectPrepareInput): EffectJournalAppend<EffectPreparedRecord>;
|
|
262
|
+
dispatch(input: EffectDispatchInput): EffectDispatchAppend;
|
|
263
|
+
outcomeForSigning(input: EffectOutcomeSigningInput): UnsignedEffectOutcomeRecord;
|
|
264
|
+
recordOutcome(outcome: EffectOutcomeRecord, providerLookupEvidence?: ProviderLookupEvidence): EffectJournalAppend<EffectOutcomeRecord>;
|
|
265
|
+
private now;
|
|
266
|
+
private validateStoredEffect;
|
|
267
|
+
private verifyDispatchSignature;
|
|
268
|
+
private verifyEndpointOutcome;
|
|
269
|
+
private verifyProviderLookupEvidence;
|
|
270
|
+
private assertFreshOutcome;
|
|
271
|
+
private verifiedSnapshots;
|
|
272
|
+
private validateHistory;
|
|
273
|
+
private operationEpochs;
|
|
274
|
+
private dispatchedMatchesPrepared;
|
|
275
|
+
private outcomeMatchesEpoch;
|
|
276
|
+
private providerIdempotencyToken;
|
|
277
|
+
}
|
|
278
|
+
export {};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { type Counter } from "../domain/counter";
|
|
2
|
+
import type { RecoveryFrontier, RecoveryLedger, RecoveryLedgerEntry, RecoveryLedgerReceipt } from "./repository";
|
|
3
|
+
export interface SignedLogFrontier {
|
|
4
|
+
readonly catalogIncarnation: string;
|
|
5
|
+
readonly sequence: Counter;
|
|
6
|
+
readonly hash: string;
|
|
7
|
+
readonly signatureDigest: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SignedLogRecord<T> extends SignedLogFrontier {
|
|
10
|
+
readonly previousHash: string;
|
|
11
|
+
readonly payload: T;
|
|
12
|
+
readonly payloadDigest: string;
|
|
13
|
+
readonly receiptDigest: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SignedLogSnapshot<T> {
|
|
16
|
+
readonly frontier: SignedLogFrontier;
|
|
17
|
+
readonly records: readonly SignedLogRecord<T>[];
|
|
18
|
+
}
|
|
19
|
+
export interface OwnerOnlySignedAppendLogOptions<T> {
|
|
20
|
+
readonly path: string;
|
|
21
|
+
readonly catalogIncarnation: string;
|
|
22
|
+
readonly signingKey: Uint8Array;
|
|
23
|
+
readonly logKind: string;
|
|
24
|
+
readonly validatePayload: (value: unknown) => T;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A process-independent, owner-only, signed append log. The companion anchor is
|
|
28
|
+
* deliberately stored outside the append stream so truncating a valid prefix is
|
|
29
|
+
* detected. It is an internal building block, not an authorization source.
|
|
30
|
+
*/
|
|
31
|
+
export declare class OwnerOnlySignedAppendLog<T> {
|
|
32
|
+
readonly path: string;
|
|
33
|
+
readonly anchorPath: string;
|
|
34
|
+
private readonly parentPath;
|
|
35
|
+
private readonly lockPath;
|
|
36
|
+
private readonly signingKey;
|
|
37
|
+
private readonly catalogIncarnation;
|
|
38
|
+
private readonly logKind;
|
|
39
|
+
private readonly validatePayload;
|
|
40
|
+
private lastObserved?;
|
|
41
|
+
constructor(options: OwnerOnlySignedAppendLogOptions<T>);
|
|
42
|
+
readSnapshot(): SignedLogSnapshot<T>;
|
|
43
|
+
verifyFrontier(frontier: SignedLogFrontier): boolean;
|
|
44
|
+
append(expected: SignedLogFrontier, payload: T): SignedLogRecord<T>;
|
|
45
|
+
private initialize;
|
|
46
|
+
private scan;
|
|
47
|
+
private parseCanonicalLine;
|
|
48
|
+
private readAnchor;
|
|
49
|
+
private writeAnchor;
|
|
50
|
+
private signFrontier;
|
|
51
|
+
private hmac;
|
|
52
|
+
private withLock;
|
|
53
|
+
}
|
|
54
|
+
export interface FileRecoveryLedgerOptions {
|
|
55
|
+
readonly path: string;
|
|
56
|
+
readonly catalogIncarnation: string;
|
|
57
|
+
readonly signingKey: Uint8Array;
|
|
58
|
+
}
|
|
59
|
+
/** Owner-only, fsync-backed RecoveryLedger implementation for local deployments. */
|
|
60
|
+
export declare class FileRecoveryLedger implements RecoveryLedger {
|
|
61
|
+
private readonly log;
|
|
62
|
+
constructor(options: FileRecoveryLedgerOptions);
|
|
63
|
+
readFreshFrontier(): RecoveryFrontier;
|
|
64
|
+
append(expected: RecoveryFrontier, entry: RecoveryLedgerEntry): RecoveryLedgerReceipt;
|
|
65
|
+
verifyFrontier(frontier: RecoveryFrontier): boolean;
|
|
66
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { CredentialBinding, CredentialOperation, EntityKind, EntityMap } from "../domain/models";
|
|
2
|
+
import type { AccountEvent, AccountsRepository, MutationContext, MutationResult, RepositoryDoctor, EligibilitySnapshot, CredentialHandleEnvelope, CredentialHandleVerifier, CredentialResolutionGrant, CredentialResolutionTransport, CredentialUseAuthorizer, NativeRevocationRequest, NativeRevocationResult, OutboxRecord, OutboxAcknowledgeRequest, OutboxClaimRequest, RecoveryLedger, ResolvedCredentialHandle, AuthorityPromotionKind, VerifiedAuthorityEvidenceRecord } from "./repository";
|
|
3
|
+
import { type Counter } from "../domain/counter";
|
|
4
|
+
export declare class InMemoryAccountsRepository implements AccountsRepository {
|
|
5
|
+
private readonly credentialVerifier;
|
|
6
|
+
private readonly recoveryLedger;
|
|
7
|
+
private readonly credentialUseAuthorizer;
|
|
8
|
+
private readonly records;
|
|
9
|
+
private readonly eventLog;
|
|
10
|
+
private readonly idempotency;
|
|
11
|
+
private readonly handles;
|
|
12
|
+
private readonly operationLog;
|
|
13
|
+
private readonly outboxLog;
|
|
14
|
+
private readonly nativeRevocationReplays;
|
|
15
|
+
private readonly authorityEvidenceByNonce;
|
|
16
|
+
private databaseFrontier?;
|
|
17
|
+
private recoveryHold;
|
|
18
|
+
private closed;
|
|
19
|
+
constructor(credentialVerifier?: CredentialHandleVerifier, recoveryLedger?: RecoveryLedger, credentialUseAuthorizer?: CredentialUseAuthorizer);
|
|
20
|
+
get<K extends EntityKind>(kind: K, id: EntityMap[K]["id"]): Promise<EntityMap[K] | undefined>;
|
|
21
|
+
list<K extends EntityKind>(kind: K): Promise<readonly EntityMap[K][]>;
|
|
22
|
+
readEligibilitySnapshot(accessMethodId: EntityMap["access_method"]["id"]): Promise<EligibilitySnapshot>;
|
|
23
|
+
insert<K extends EntityKind>(kind: K, input: EntityMap[K], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
|
|
24
|
+
insertCapacityPoolWithAuthorityEvidence(input: EntityMap["capacity_pool"], inputEvidence: VerifiedAuthorityEvidenceRecord, context: MutationContext): Promise<MutationResult<EntityMap["capacity_pool"]>>;
|
|
25
|
+
insertCredentialBinding(input: CredentialBinding, inputHandle: CredentialHandleEnvelope, context: MutationContext): Promise<MutationResult<CredentialBinding>>;
|
|
26
|
+
resolveCredentialHandle(bindingId: CredentialBinding["id"], grant: CredentialResolutionGrant, transport: CredentialResolutionTransport): Promise<ResolvedCredentialHandle>;
|
|
27
|
+
replace<K extends EntityKind>(kind: K, input: EntityMap[K], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
|
|
28
|
+
promoteWithAuthorityEvidence<K extends AuthorityPromotionKind>(kind: K, input: EntityMap[K], expectedRevision: Counter, inputEvidence: readonly VerifiedAuthorityEvidenceRecord[], context: MutationContext): Promise<MutationResult<EntityMap[K]>>;
|
|
29
|
+
revokeNativeGeneration(request: NativeRevocationRequest): Promise<NativeRevocationResult>;
|
|
30
|
+
credentialOperations(): Promise<readonly CredentialOperation[]>;
|
|
31
|
+
outbox(): Promise<readonly OutboxRecord[]>;
|
|
32
|
+
claimOutbox(request: OutboxClaimRequest): Promise<readonly OutboxRecord[]>;
|
|
33
|
+
acknowledgeOutbox(request: OutboxAcknowledgeRequest): Promise<OutboxRecord>;
|
|
34
|
+
events(): Promise<readonly AccountEvent[]>;
|
|
35
|
+
findReplacementReplay<K extends EntityKind>(kind: K, id: EntityMap[K]["id"], to: EntityMap[K]["status"], expectedRevision: Counter, context: MutationContext): Promise<MutationResult<EntityMap[K]> | undefined>;
|
|
36
|
+
doctor(): Promise<RepositoryDoctor>;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
private readRecoverySnapshot;
|
|
39
|
+
private appendRecovery;
|
|
40
|
+
private commitRecovery;
|
|
41
|
+
private replay;
|
|
42
|
+
private makeEvent;
|
|
43
|
+
private appendAggregateOutbox;
|
|
44
|
+
private appendCleanupOutbox;
|
|
45
|
+
private assertUniqueness;
|
|
46
|
+
private assertOpen;
|
|
47
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AccessMethod, AuthCapsule, CapacityPool, CredentialBinding } from "../domain/models";
|
|
2
|
+
import type { NativeRevocationRequest, NativeRevocationResult } from "./repository";
|
|
3
|
+
export interface NativeRevocationSource {
|
|
4
|
+
readonly pool: CapacityPool;
|
|
5
|
+
readonly method: AccessMethod;
|
|
6
|
+
readonly capsule: AuthCapsule;
|
|
7
|
+
readonly binding: CredentialBinding;
|
|
8
|
+
readonly credentialHandleAuditDigest: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function deriveNativeRevocation(source: NativeRevocationSource, request: NativeRevocationRequest, revocationBarrierReceiptDigest: string): Omit<NativeRevocationResult, "replayed">;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface PostgresConnectionInput {
|
|
2
|
+
readonly url: string | URL;
|
|
3
|
+
/** Test-only escape hatch. It is accepted exclusively for a literal loopback host. */
|
|
4
|
+
readonly allowInsecureLoopback?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface NormalizedPostgresConnection {
|
|
7
|
+
readonly url: URL;
|
|
8
|
+
readonly tls: false | Readonly<{
|
|
9
|
+
rejectUnauthorized: true;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
export interface PostgresRuntimeContext {
|
|
13
|
+
readonly principalRef: string;
|
|
14
|
+
readonly identityRealm: "hasna";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates the connection without ever including the credential-bearing URL in
|
|
18
|
+
* an exception. Self-hosted Accounts only accepts hostname-verified TLS. The
|
|
19
|
+
* sole plaintext exception is an explicit literal-loopback test connection.
|
|
20
|
+
*/
|
|
21
|
+
export declare function normalizePostgresConnection(input: PostgresConnectionInput): NormalizedPostgresConnection;
|
|
22
|
+
export declare function validatePostgresRuntimeContext(input: {
|
|
23
|
+
readonly principalRef: string;
|
|
24
|
+
readonly identityRealm: string;
|
|
25
|
+
}): PostgresRuntimeContext;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const POSTGRES_SCHEMA_VERSION = 1;
|
|
2
|
+
export declare const POSTGRES_REQUIRED_TABLES: readonly ["schema_migrations", "accounts_installation", "provider_accounts", "provider_subject_claims", "entitlements", "capacity_pools", "capacity_domain_claims", "account_lanes", "auth_capsules", "credential_family_claims", "credential_bindings", "credential_binding_handles", "credential_operations", "import_candidates", "evidence_records", "recovery_ledger_receipts", "slot_eligibility_audit", "account_events", "outbox", "idempotency_records"];
|
|
3
|
+
export declare const POSTGRES_MIGRATION_V1: string;
|
|
4
|
+
export declare const POSTGRES_MIGRATION_V1_CHECKSUM: string;
|
|
5
|
+
export declare const POSTGRES_MIGRATION_CHECKSUM: string;
|
|
6
|
+
export declare const POSTGRES_MIGRATIONS: readonly Readonly<{
|
|
7
|
+
version: 1;
|
|
8
|
+
checksum: string;
|
|
9
|
+
sql: string;
|
|
10
|
+
}>[];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SQL } from "bun";
|
|
2
|
+
export interface PostgresMigrationReport {
|
|
3
|
+
readonly schemaVersion: string;
|
|
4
|
+
readonly migrationChecksum: string;
|
|
5
|
+
readonly appliedVersions: readonly string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Applies only package-owned, checksummed SQL while holding a transaction-level
|
|
9
|
+
* advisory lock. This function must be called with the migration/admin client,
|
|
10
|
+
* never with the Accounts runtime role.
|
|
11
|
+
*/
|
|
12
|
+
export declare function runPostgresMigrations(client: SQL): Promise<PostgresMigrationReport>;
|