life-as-api 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +377 -0
- package/dist/agent/finance-agent.d.ts +44 -0
- package/dist/agent/finance-agent.js +75 -0
- package/dist/agent/finance-agent.js.map +1 -0
- package/dist/agent/legal-agent.d.ts +44 -0
- package/dist/agent/legal-agent.js +76 -0
- package/dist/agent/legal-agent.js.map +1 -0
- package/dist/agent/medical-agent.d.ts +44 -0
- package/dist/agent/medical-agent.js +75 -0
- package/dist/agent/medical-agent.js.map +1 -0
- package/dist/agent/trusted-agent-registry.d.ts +53 -0
- package/dist/agent/trusted-agent-registry.js +57 -0
- package/dist/agent/trusted-agent-registry.js.map +1 -0
- package/dist/audit/audit-chain-verifier.d.ts +10 -0
- package/dist/audit/audit-chain-verifier.js +67 -0
- package/dist/audit/audit-chain-verifier.js.map +1 -0
- package/dist/audit/audit-log.d.ts +48 -0
- package/dist/audit/audit-log.js +74 -0
- package/dist/audit/audit-log.js.map +1 -0
- package/dist/audit/sqlite-audit-log.d.ts +29 -0
- package/dist/audit/sqlite-audit-log.js +142 -0
- package/dist/audit/sqlite-audit-log.js.map +1 -0
- package/dist/auth/access-context-issuer.d.ts +18 -0
- package/dist/auth/access-context-issuer.js +88 -0
- package/dist/auth/access-context-issuer.js.map +1 -0
- package/dist/auth/assert-authorized-for-subject.d.ts +2 -0
- package/dist/auth/assert-authorized-for-subject.js +20 -0
- package/dist/auth/assert-authorized-for-subject.js.map +1 -0
- package/dist/auth/backend-context-minting-boundary.d.ts +23 -0
- package/dist/auth/backend-context-minting-boundary.js +281 -0
- package/dist/auth/backend-context-minting-boundary.js.map +1 -0
- package/dist/auth/default-authorization-policy.d.ts +7 -0
- package/dist/auth/default-authorization-policy.js +64 -0
- package/dist/auth/default-authorization-policy.js.map +1 -0
- package/dist/auth/fake-auth-adapter.d.ts +7 -0
- package/dist/auth/fake-auth-adapter.js +27 -0
- package/dist/auth/fake-auth-adapter.js.map +1 -0
- package/dist/auth/http-client.d.ts +12 -0
- package/dist/auth/http-client.js +7 -0
- package/dist/auth/http-client.js.map +1 -0
- package/dist/auth/in-memory-grant-resolver.d.ts +21 -0
- package/dist/auth/in-memory-grant-resolver.js +73 -0
- package/dist/auth/in-memory-grant-resolver.js.map +1 -0
- package/dist/auth/in-memory-tenant-boundary.d.ts +16 -0
- package/dist/auth/in-memory-tenant-boundary.js +37 -0
- package/dist/auth/in-memory-tenant-boundary.js.map +1 -0
- package/dist/auth/jwks-key-ring-auth-adapter.d.ts +38 -0
- package/dist/auth/jwks-key-ring-auth-adapter.js +123 -0
- package/dist/auth/jwks-key-ring-auth-adapter.js.map +1 -0
- package/dist/auth/jwks-key-ring.d.ts +25 -0
- package/dist/auth/jwks-key-ring.js +111 -0
- package/dist/auth/jwks-key-ring.js.map +1 -0
- package/dist/auth/jwt-auth-adapter.d.ts +15 -0
- package/dist/auth/jwt-auth-adapter.js +59 -0
- package/dist/auth/jwt-auth-adapter.js.map +1 -0
- package/dist/auth/jwt-core.d.ts +32 -0
- package/dist/auth/jwt-core.js +226 -0
- package/dist/auth/jwt-core.js.map +1 -0
- package/dist/auth/jwt-key-ring-auth-adapter.d.ts +16 -0
- package/dist/auth/jwt-key-ring-auth-adapter.js +58 -0
- package/dist/auth/jwt-key-ring-auth-adapter.js.map +1 -0
- package/dist/auth/oidc-discovery.d.ts +15 -0
- package/dist/auth/oidc-discovery.js +46 -0
- package/dist/auth/oidc-discovery.js.map +1 -0
- package/dist/auth/production-scoped-life-api.d.ts +58 -0
- package/dist/auth/production-scoped-life-api.js +802 -0
- package/dist/auth/production-scoped-life-api.js.map +1 -0
- package/dist/auth/proposal-scope-inspector.d.ts +3 -0
- package/dist/auth/proposal-scope-inspector.js +42 -0
- package/dist/auth/proposal-scope-inspector.js.map +1 -0
- package/dist/auth/proposal-scoped-life-api.d.ts +21 -0
- package/dist/auth/proposal-scoped-life-api.js +168 -0
- package/dist/auth/proposal-scoped-life-api.js.map +1 -0
- package/dist/auth/rate-limited-context-minting-boundary.d.ts +27 -0
- package/dist/auth/rate-limited-context-minting-boundary.js +77 -0
- package/dist/auth/rate-limited-context-minting-boundary.js.map +1 -0
- package/dist/auth/revocation-aware-auth-adapter.d.ts +21 -0
- package/dist/auth/revocation-aware-auth-adapter.js +88 -0
- package/dist/auth/revocation-aware-auth-adapter.js.map +1 -0
- package/dist/auth/sqlite-grant-resolver.d.ts +8 -0
- package/dist/auth/sqlite-grant-resolver.js +78 -0
- package/dist/auth/sqlite-grant-resolver.js.map +1 -0
- package/dist/auth/sqlite-tenant-boundary.d.ts +7 -0
- package/dist/auth/sqlite-tenant-boundary.js +41 -0
- package/dist/auth/sqlite-tenant-boundary.js.map +1 -0
- package/dist/auth/static-jwt-key-ring.d.ts +13 -0
- package/dist/auth/static-jwt-key-ring.js +73 -0
- package/dist/auth/static-jwt-key-ring.js.map +1 -0
- package/dist/auth/subject-scoped-life-api.d.ts +14 -0
- package/dist/auth/subject-scoped-life-api.js +51 -0
- package/dist/auth/subject-scoped-life-api.js.map +1 -0
- package/dist/auth/test-context-minting-boundary.d.ts +13 -0
- package/dist/auth/test-context-minting-boundary.js +74 -0
- package/dist/auth/test-context-minting-boundary.js.map +1 -0
- package/dist/auth/types.d.ts +77 -0
- package/dist/auth/types.js +16 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/compliance/subject-data-report.d.ts +43 -0
- package/dist/compliance/subject-data-report.js +155 -0
- package/dist/compliance/subject-data-report.js.map +1 -0
- package/dist/consent/consent-guard.d.ts +4 -0
- package/dist/consent/consent-guard.js +37 -0
- package/dist/consent/consent-guard.js.map +1 -0
- package/dist/consent/grant-registry.d.ts +7 -0
- package/dist/consent/grant-registry.js +13 -0
- package/dist/consent/grant-registry.js.map +1 -0
- package/dist/consent/intersect-selector.d.ts +3 -0
- package/dist/consent/intersect-selector.js +66 -0
- package/dist/consent/intersect-selector.js.map +1 -0
- package/dist/contract/diagnostics.d.ts +32 -0
- package/dist/contract/diagnostics.js +112 -0
- package/dist/contract/diagnostics.js.map +1 -0
- package/dist/contract/project-contracts.d.ts +5 -0
- package/dist/contract/project-contracts.js +159 -0
- package/dist/contract/project-contracts.js.map +1 -0
- package/dist/contract/types.d.ts +32 -0
- package/dist/contract/types.js +5 -0
- package/dist/contract/types.js.map +1 -0
- package/dist/crypto/aes-gcm.d.ts +11 -0
- package/dist/crypto/aes-gcm.js +78 -0
- package/dist/crypto/aes-gcm.js.map +1 -0
- package/dist/crypto/claim-serializer.d.ts +26 -0
- package/dist/crypto/claim-serializer.js +59 -0
- package/dist/crypto/claim-serializer.js.map +1 -0
- package/dist/crypto/sha256.d.ts +12 -0
- package/dist/crypto/sha256.js +40 -0
- package/dist/crypto/sha256.js.map +1 -0
- package/dist/crypto/static-key.d.ts +11 -0
- package/dist/crypto/static-key.js +60 -0
- package/dist/crypto/static-key.js.map +1 -0
- package/dist/crypto/types.d.ts +20 -0
- package/dist/crypto/types.js +8 -0
- package/dist/crypto/types.js.map +1 -0
- package/dist/datasource/trusted-data-source-registry.d.ts +51 -0
- package/dist/datasource/trusted-data-source-registry.js +57 -0
- package/dist/datasource/trusted-data-source-registry.js.map +1 -0
- package/dist/erasure/tombstone.d.ts +13 -0
- package/dist/erasure/tombstone.js +20 -0
- package/dist/erasure/tombstone.js.map +1 -0
- package/dist/evidence/evidence-backed-claim-creator.d.ts +48 -0
- package/dist/evidence/evidence-backed-claim-creator.js +107 -0
- package/dist/evidence/evidence-backed-claim-creator.js.map +1 -0
- package/dist/evidence/in-memory-raw-document-store.d.ts +26 -0
- package/dist/evidence/in-memory-raw-document-store.js +84 -0
- package/dist/evidence/in-memory-raw-document-store.js.map +1 -0
- package/dist/evidence/raw-document-store.d.ts +12 -0
- package/dist/evidence/raw-document-store.js +8 -0
- package/dist/evidence/raw-document-store.js.map +1 -0
- package/dist/evidence/source-evidence-validator.d.ts +4 -0
- package/dist/evidence/source-evidence-validator.js +14 -0
- package/dist/evidence/source-evidence-validator.js.map +1 -0
- package/dist/evidence/sqlite-raw-document-store.d.ts +19 -0
- package/dist/evidence/sqlite-raw-document-store.js +122 -0
- package/dist/evidence/sqlite-raw-document-store.js.map +1 -0
- package/dist/guardian/guardian-registry.d.ts +96 -0
- package/dist/guardian/guardian-registry.js +95 -0
- package/dist/guardian/guardian-registry.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/observability/health.d.ts +12 -0
- package/dist/observability/health.js +16 -0
- package/dist/observability/health.js.map +1 -0
- package/dist/observability/logger.d.ts +21 -0
- package/dist/observability/logger.js +40 -0
- package/dist/observability/logger.js.map +1 -0
- package/dist/observability/metrics.d.ts +15 -0
- package/dist/observability/metrics.js +52 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/persistence/backup.d.ts +24 -0
- package/dist/persistence/backup.js +251 -0
- package/dist/persistence/backup.js.map +1 -0
- package/dist/persistence/decryptability-scan.d.ts +10 -0
- package/dist/persistence/decryptability-scan.js +144 -0
- package/dist/persistence/decryptability-scan.js.map +1 -0
- package/dist/persistence/in-memory-unit-of-work.d.ts +11 -0
- package/dist/persistence/in-memory-unit-of-work.js +32 -0
- package/dist/persistence/in-memory-unit-of-work.js.map +1 -0
- package/dist/persistence/key-availability.d.ts +9 -0
- package/dist/persistence/key-availability.js +125 -0
- package/dist/persistence/key-availability.js.map +1 -0
- package/dist/persistence/sqlite/migrations.d.ts +9 -0
- package/dist/persistence/sqlite/migrations.js +535 -0
- package/dist/persistence/sqlite/migrations.js.map +1 -0
- package/dist/persistence/sqlite/schema.d.ts +10 -0
- package/dist/persistence/sqlite/schema.js +101 -0
- package/dist/persistence/sqlite/schema.js.map +1 -0
- package/dist/persistence/sqlite/sqlite-fact-store.d.ts +24 -0
- package/dist/persistence/sqlite/sqlite-fact-store.js +207 -0
- package/dist/persistence/sqlite/sqlite-fact-store.js.map +1 -0
- package/dist/persistence/sqlite/sqlite-source-registry.d.ts +17 -0
- package/dist/persistence/sqlite/sqlite-source-registry.js +132 -0
- package/dist/persistence/sqlite/sqlite-source-registry.js.map +1 -0
- package/dist/persistence/sqlite/sqlite-unit-of-work.d.ts +8 -0
- package/dist/persistence/sqlite/sqlite-unit-of-work.js +41 -0
- package/dist/persistence/sqlite/sqlite-unit-of-work.js.map +1 -0
- package/dist/persistence/sqlite/types.d.ts +24 -0
- package/dist/persistence/sqlite/types.js +28 -0
- package/dist/persistence/sqlite/types.js.map +1 -0
- package/dist/persistence/unit-of-work.d.ts +6 -0
- package/dist/persistence/unit-of-work.js +15 -0
- package/dist/persistence/unit-of-work.js.map +1 -0
- package/dist/proposal/accepted-claim-appender.d.ts +7 -0
- package/dist/proposal/accepted-claim-appender.js +16 -0
- package/dist/proposal/accepted-claim-appender.js.map +1 -0
- package/dist/proposal/in-memory-proposal-queue.d.ts +21 -0
- package/dist/proposal/in-memory-proposal-queue.js +218 -0
- package/dist/proposal/in-memory-proposal-queue.js.map +1 -0
- package/dist/proposal/policy-aware-proposal-queue.d.ts +23 -0
- package/dist/proposal/policy-aware-proposal-queue.js +162 -0
- package/dist/proposal/policy-aware-proposal-queue.js.map +1 -0
- package/dist/proposal/proposal-policy.d.ts +37 -0
- package/dist/proposal/proposal-policy.js +72 -0
- package/dist/proposal/proposal-policy.js.map +1 -0
- package/dist/proposal/proposal-queue.d.ts +13 -0
- package/dist/proposal/proposal-queue.js +15 -0
- package/dist/proposal/proposal-queue.js.map +1 -0
- package/dist/proposal/source-aware-claim-appender.d.ts +13 -0
- package/dist/proposal/source-aware-claim-appender.js +47 -0
- package/dist/proposal/source-aware-claim-appender.js.map +1 -0
- package/dist/proposal/sqlite-proposal-queue.d.ts +26 -0
- package/dist/proposal/sqlite-proposal-queue.js +282 -0
- package/dist/proposal/sqlite-proposal-queue.js.map +1 -0
- package/dist/resolution/resolve-claims.d.ts +4 -0
- package/dist/resolution/resolve-claims.js +101 -0
- package/dist/resolution/resolve-claims.js.map +1 -0
- package/dist/resolution/trust-profile.d.ts +12 -0
- package/dist/resolution/trust-profile.js +23 -0
- package/dist/resolution/trust-profile.js.map +1 -0
- package/dist/resolution/types.d.ts +15 -0
- package/dist/resolution/types.js +8 -0
- package/dist/resolution/types.js.map +1 -0
- package/dist/sdk/create-backend-integrated-life-api-for-test.d.ts +23 -0
- package/dist/sdk/create-backend-integrated-life-api-for-test.js +240 -0
- package/dist/sdk/create-backend-integrated-life-api-for-test.js.map +1 -0
- package/dist/sdk/create-life-api.d.ts +55 -0
- package/dist/sdk/create-life-api.js +251 -0
- package/dist/sdk/create-life-api.js.map +1 -0
- package/dist/sdk/create-sqlite-life-api.d.ts +33 -0
- package/dist/sdk/create-sqlite-life-api.js +654 -0
- package/dist/sdk/create-sqlite-life-api.js.map +1 -0
- package/dist/sdk/life-api.d.ts +27 -0
- package/dist/sdk/life-api.js +17 -0
- package/dist/sdk/life-api.js.map +1 -0
- package/dist/sdk/validation.d.ts +8 -0
- package/dist/sdk/validation.js +216 -0
- package/dist/sdk/validation.js.map +1 -0
- package/dist/source/in-memory-source-registry.d.ts +15 -0
- package/dist/source/in-memory-source-registry.js +104 -0
- package/dist/source/in-memory-source-registry.js.map +1 -0
- package/dist/source/source-aware-fact-store.d.ts +19 -0
- package/dist/source/source-aware-fact-store.js +40 -0
- package/dist/source/source-aware-fact-store.js.map +1 -0
- package/dist/source/source-kind-predicate-policy.d.ts +4 -0
- package/dist/source/source-kind-predicate-policy.js +62 -0
- package/dist/source/source-kind-predicate-policy.js.map +1 -0
- package/dist/source/source-registry.d.ts +11 -0
- package/dist/source/source-registry.js +12 -0
- package/dist/source/source-registry.js.map +1 -0
- package/dist/store/in-memory-fact-store.d.ts +25 -0
- package/dist/store/in-memory-fact-store.js +192 -0
- package/dist/store/in-memory-fact-store.js.map +1 -0
- package/dist/surface/context-query.d.ts +21 -0
- package/dist/surface/context-query.js +113 -0
- package/dist/surface/context-query.js.map +1 -0
- package/dist/surface/evidence-backed-context-query.d.ts +62 -0
- package/dist/surface/evidence-backed-context-query.js +240 -0
- package/dist/surface/evidence-backed-context-query.js.map +1 -0
- package/dist/types/access-context.d.ts +25 -0
- package/dist/types/access-context.js +6 -0
- package/dist/types/access-context.js.map +1 -0
- package/dist/types/claim.d.ts +48 -0
- package/dist/types/claim.js +5 -0
- package/dist/types/claim.js.map +1 -0
- package/dist/types/consent.d.ts +41 -0
- package/dist/types/consent.js +3 -0
- package/dist/types/consent.js.map +1 -0
- package/dist/types/crypto-boundary.d.ts +12 -0
- package/dist/types/crypto-boundary.js +15 -0
- package/dist/types/crypto-boundary.js.map +1 -0
- package/dist/types/evidence.d.ts +31 -0
- package/dist/types/evidence.js +8 -0
- package/dist/types/evidence.js.map +1 -0
- package/dist/types/fact-store.d.ts +24 -0
- package/dist/types/fact-store.js +12 -0
- package/dist/types/fact-store.js.map +1 -0
- package/dist/types/ids.d.ts +36 -0
- package/dist/types/ids.js +11 -0
- package/dist/types/ids.js.map +1 -0
- package/dist/types/proposal.d.ts +38 -0
- package/dist/types/proposal.js +7 -0
- package/dist/types/proposal.js.map +1 -0
- package/dist/types/source.d.ts +33 -0
- package/dist/types/source.js +6 -0
- package/dist/types/source.js.map +1 -0
- package/dist/types/trust.d.ts +24 -0
- package/dist/types/trust.js +5 -0
- package/dist/types/trust.js.map +1 -0
- package/dist/utilities/deep-freeze.d.ts +1 -0
- package/dist/utilities/deep-freeze.js +17 -0
- package/dist/utilities/deep-freeze.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ClaimId, ContractId, ISOTime, PersonId, SourceId } from "../types/ids.js";
|
|
2
|
+
import type { ClaimPredicate, StoredClaim } from "../types/claim.js";
|
|
3
|
+
import type { CryptoBoundary, EncryptedBlob } from "./types.js";
|
|
4
|
+
export interface SerializedClaim {
|
|
5
|
+
readonly id: ClaimId;
|
|
6
|
+
readonly sourceId: SourceId;
|
|
7
|
+
readonly subject: PersonId;
|
|
8
|
+
readonly predicate: ClaimPredicate;
|
|
9
|
+
readonly validFrom: ISOTime;
|
|
10
|
+
readonly validTo?: ISOTime;
|
|
11
|
+
readonly recordedAt: ISOTime;
|
|
12
|
+
readonly recordedSeq: number;
|
|
13
|
+
readonly retracts?: ClaimId;
|
|
14
|
+
readonly supersedes?: ClaimId;
|
|
15
|
+
readonly overrides?: ClaimId;
|
|
16
|
+
readonly contractId?: ContractId;
|
|
17
|
+
readonly confidence?: number;
|
|
18
|
+
readonly serializerVersion: string;
|
|
19
|
+
readonly encryptedPayload: EncryptedBlob;
|
|
20
|
+
}
|
|
21
|
+
export declare class ClaimSerializer {
|
|
22
|
+
private readonly _crypto;
|
|
23
|
+
constructor(_crypto: CryptoBoundary);
|
|
24
|
+
serializeClaimForPersistence(claim: StoredClaim): Promise<SerializedClaim>;
|
|
25
|
+
deserializeClaimFromPersistence(serialized: SerializedClaim): Promise<StoredClaim>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Slice-05: ClaimSerializer — persistence boundary adapter.
|
|
2
|
+
//
|
|
3
|
+
// Converts StoredClaim ↔ SerializedClaim.
|
|
4
|
+
// payload is encrypted via CryptoBoundary; all ClaimMeta fields remain plaintext.
|
|
5
|
+
//
|
|
6
|
+
// CRYPTO_PAYLOAD_AT_REST_001: encryptedPayload replaces plaintext payload in SerializedClaim.
|
|
7
|
+
// CRYPTO_METADATA_PLAINTEXT_ACCEPTED_001: metadata fields not encrypted (documented risk).
|
|
8
|
+
// CRYPTO_ROUND_TRIP_001: serialize → deserialize restores byte-identical payload.
|
|
9
|
+
//
|
|
10
|
+
// This file DOES NOT import crypto primitives. It depends on CryptoBoundary interface.
|
|
11
|
+
// Domain/store modules must NOT import this file — it belongs to the persistence boundary.
|
|
12
|
+
import { deepFreeze } from "../utilities/deep-freeze.js";
|
|
13
|
+
export class ClaimSerializer {
|
|
14
|
+
_crypto;
|
|
15
|
+
constructor(_crypto) {
|
|
16
|
+
this._crypto = _crypto;
|
|
17
|
+
}
|
|
18
|
+
async serializeClaimForPersistence(claim) {
|
|
19
|
+
const encryptedPayload = await this._crypto.encryptJson(claim.payload);
|
|
20
|
+
return {
|
|
21
|
+
id: claim.id,
|
|
22
|
+
sourceId: claim.sourceId,
|
|
23
|
+
subject: claim.subject,
|
|
24
|
+
predicate: claim.predicate,
|
|
25
|
+
validFrom: claim.validFrom,
|
|
26
|
+
recordedAt: claim.recordedAt,
|
|
27
|
+
recordedSeq: claim.recordedSeq,
|
|
28
|
+
serializerVersion: "claim-serializer-v1",
|
|
29
|
+
encryptedPayload,
|
|
30
|
+
// exactOptionalPropertyTypes: only spread optional fields when present
|
|
31
|
+
...(claim.validTo !== undefined ? { validTo: claim.validTo } : {}),
|
|
32
|
+
...(claim.retracts !== undefined ? { retracts: claim.retracts } : {}),
|
|
33
|
+
...(claim.supersedes !== undefined ? { supersedes: claim.supersedes } : {}),
|
|
34
|
+
...(claim.overrides !== undefined ? { overrides: claim.overrides } : {}),
|
|
35
|
+
...(claim.contractId !== undefined ? { contractId: claim.contractId } : {}),
|
|
36
|
+
...(claim.confidence !== undefined ? { confidence: claim.confidence } : {}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
async deserializeClaimFromPersistence(serialized) {
|
|
40
|
+
const payload = (await this._crypto.decryptJson(serialized.encryptedPayload));
|
|
41
|
+
return deepFreeze({
|
|
42
|
+
id: serialized.id,
|
|
43
|
+
sourceId: serialized.sourceId,
|
|
44
|
+
subject: serialized.subject,
|
|
45
|
+
predicate: serialized.predicate,
|
|
46
|
+
validFrom: serialized.validFrom,
|
|
47
|
+
recordedAt: serialized.recordedAt,
|
|
48
|
+
recordedSeq: serialized.recordedSeq,
|
|
49
|
+
payload,
|
|
50
|
+
...(serialized.validTo !== undefined ? { validTo: serialized.validTo } : {}),
|
|
51
|
+
...(serialized.retracts !== undefined ? { retracts: serialized.retracts } : {}),
|
|
52
|
+
...(serialized.supersedes !== undefined ? { supersedes: serialized.supersedes } : {}),
|
|
53
|
+
...(serialized.overrides !== undefined ? { overrides: serialized.overrides } : {}),
|
|
54
|
+
...(serialized.contractId !== undefined ? { contractId: serialized.contractId } : {}),
|
|
55
|
+
...(serialized.confidence !== undefined ? { confidence: serialized.confidence } : {}),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=claim-serializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-serializer.js","sourceRoot":"","sources":["../../src/crypto/claim-serializer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Synchronous SHA-256 hex digest. Uses node:crypto createHash — for use in
|
|
3
|
+
* synchronous SQLite transaction callbacks (better-sqlite3 pattern).
|
|
4
|
+
* Output: lowercase 64-character hex string.
|
|
5
|
+
*/
|
|
6
|
+
export declare function sha256hexSync(input: string | Uint8Array): string;
|
|
7
|
+
/**
|
|
8
|
+
* Async SHA-256 hex digest. Uses globalThis.crypto.subtle.digest — for use in
|
|
9
|
+
* async contexts outside of synchronous transaction callbacks.
|
|
10
|
+
* Output: lowercase 64-character hex string.
|
|
11
|
+
*/
|
|
12
|
+
export declare function sha256hex(input: string | Uint8Array): Promise<string>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SHA-256 helpers — Audit Hardening C4 (Local Hash Chain).
|
|
2
|
+
//
|
|
3
|
+
// CRYPTO_BOUNDARY_ONLY_001: this file lives inside the sanctioned src/crypto/** boundary,
|
|
4
|
+
// so it may import node:crypto / use crypto.subtle. No file outside src/crypto/** does.
|
|
5
|
+
// CRYPTO_NO_DOMAIN_IMPORTS_001: this helper imports NO audit / persistence / domain modules.
|
|
6
|
+
//
|
|
7
|
+
// Two variants:
|
|
8
|
+
// - sha256hexSync: synchronous (node:crypto createHash) — for better-sqlite3 synchronous
|
|
9
|
+
// transaction callbacks (SQLiteAuditLog.write) and the synchronous migration backfill loop.
|
|
10
|
+
// - sha256hex: async (globalThis.crypto.subtle.digest) — for async contexts outside of
|
|
11
|
+
// synchronous transaction callbacks.
|
|
12
|
+
import { createHash } from "node:crypto";
|
|
13
|
+
/**
|
|
14
|
+
* Synchronous SHA-256 hex digest. Uses node:crypto createHash — for use in
|
|
15
|
+
* synchronous SQLite transaction callbacks (better-sqlite3 pattern).
|
|
16
|
+
* Output: lowercase 64-character hex string.
|
|
17
|
+
*/
|
|
18
|
+
export function sha256hexSync(input) {
|
|
19
|
+
const h = createHash("sha256");
|
|
20
|
+
if (typeof input === "string") {
|
|
21
|
+
h.update(input, "utf-8");
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
h.update(input);
|
|
25
|
+
}
|
|
26
|
+
return h.digest("hex");
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Async SHA-256 hex digest. Uses globalThis.crypto.subtle.digest — for use in
|
|
30
|
+
* async contexts outside of synchronous transaction callbacks.
|
|
31
|
+
* Output: lowercase 64-character hex string.
|
|
32
|
+
*/
|
|
33
|
+
export async function sha256hex(input) {
|
|
34
|
+
const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
|
|
35
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", new Uint8Array(bytes));
|
|
36
|
+
return [...new Uint8Array(digest)]
|
|
37
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
38
|
+
.join("");
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sha256.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sha256.js","sourceRoot":"","sources":["../../src/crypto/sha256.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,0FAA0F;AAC1F,0FAA0F;AAC1F,6FAA6F;AAC7F,EAAE;AACF,gBAAgB;AAChB,2FAA2F;AAC3F,gGAAgG;AAChG,yFAAyF;AACzF,yCAAyC;AAEzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAA0B;IACtD,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC;SAAM,CAAC;QACN,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAA0B;IACxD,MAAM,KAAK,GACT,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACtE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAClD,SAAS,EACT,IAAI,UAAU,CAAC,KAAK,CAAC,CACtB,CAAC;IACF,OAAO,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;SAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { KeyDescriptor, KeyProvider } from "./types.js";
|
|
2
|
+
export declare class StaticKeyProvider implements KeyProvider {
|
|
3
|
+
private readonly _current;
|
|
4
|
+
private readonly _allKeys;
|
|
5
|
+
constructor(current: KeyDescriptor, historical?: readonly KeyDescriptor[]);
|
|
6
|
+
getCurrentKey(): Promise<KeyDescriptor>;
|
|
7
|
+
getKey(keyId: string): Promise<KeyDescriptor | undefined>;
|
|
8
|
+
withCurrentKey(newCurrent: KeyDescriptor): StaticKeyProvider;
|
|
9
|
+
static generate(keyId: string): Promise<StaticKeyProvider>;
|
|
10
|
+
static fromRawBytes(keyId: string, rawBytes: Uint8Array): Promise<StaticKeyProvider>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// StaticKeyProvider — for tests and development only.
|
|
2
|
+
//
|
|
3
|
+
// WARNING: This provider holds static key(s) in memory.
|
|
4
|
+
// Do NOT use as a production default. Construct explicitly via StaticKeyProvider.generate().
|
|
5
|
+
// CRYPTO_KEY_PROVIDER_DI_001: no global default instance.
|
|
6
|
+
//
|
|
7
|
+
// KEY_VERSIONING_EXISTS_001: supports multiple keys for rotation boundary testing.
|
|
8
|
+
// withCurrentKey() returns a new provider where a different key is current but all
|
|
9
|
+
// previously-known keys remain resolvable — decryption uses blob.keyId, not the
|
|
10
|
+
// current key. Unknown keyId → CRYPTO_WRONG_KEY_FAIL_CLOSED_001.
|
|
11
|
+
export class StaticKeyProvider {
|
|
12
|
+
_current;
|
|
13
|
+
_allKeys;
|
|
14
|
+
// Explicit constructor — callers must supply a current descriptor.
|
|
15
|
+
// historical: additional descriptors that remain resolvable via getKey().
|
|
16
|
+
// KEY_VERSION_DUPLICATE_KEY_ID_DENIED_001: throws if any keyId appears more than once.
|
|
17
|
+
constructor(current, historical = []) {
|
|
18
|
+
this._current = current;
|
|
19
|
+
const map = new Map([[current.keyId, current]]);
|
|
20
|
+
for (const desc of historical) {
|
|
21
|
+
if (map.has(desc.keyId)) {
|
|
22
|
+
throw Object.assign(new Error(`KEY_VERSION_DUPLICATE_KEY_ID_001: keyId "${desc.keyId}" appears more than once — each keyId must map to exactly one key descriptor`), { code: "KEY_VERSION_DUPLICATE_KEY_ID_001" });
|
|
23
|
+
}
|
|
24
|
+
map.set(desc.keyId, desc);
|
|
25
|
+
}
|
|
26
|
+
this._allKeys = map;
|
|
27
|
+
}
|
|
28
|
+
async getCurrentKey() {
|
|
29
|
+
return this._current;
|
|
30
|
+
}
|
|
31
|
+
async getKey(keyId) {
|
|
32
|
+
return this._allKeys.get(keyId);
|
|
33
|
+
}
|
|
34
|
+
// Returns a new provider where newCurrent is the active encryption key and all
|
|
35
|
+
// previously-known keys (including the old current) are still resolvable for
|
|
36
|
+
// decryption. This is the rotation boundary: old blobs keep working.
|
|
37
|
+
// KEY_VERSION_DUPLICATE_KEY_ID_DENIED_001: throws if newCurrent.keyId is already
|
|
38
|
+
// registered — rotating to a known keyId would create key-material ambiguity.
|
|
39
|
+
withCurrentKey(newCurrent) {
|
|
40
|
+
if (this._allKeys.has(newCurrent.keyId)) {
|
|
41
|
+
throw Object.assign(new Error(`KEY_VERSION_DUPLICATE_KEY_ID_001: cannot rotate to keyId "${newCurrent.keyId}" — it is already registered in this provider; key id reuse is forbidden`), { code: "KEY_VERSION_DUPLICATE_KEY_ID_001" });
|
|
42
|
+
}
|
|
43
|
+
return new StaticKeyProvider(newCurrent, [...this._allKeys.values()]);
|
|
44
|
+
}
|
|
45
|
+
// Factory: generate a fresh random AES-256 key.
|
|
46
|
+
// Uses WebCrypto — no node:crypto import (CRYPTO_BOUNDARY_ONLY_001).
|
|
47
|
+
static async generate(keyId) {
|
|
48
|
+
const key = await globalThis.crypto.subtle.generateKey({ name: "AES-GCM", length: 256 }, true, // extractable for testing/export
|
|
49
|
+
["encrypt", "decrypt"]);
|
|
50
|
+
return new StaticKeyProvider({ keyId, key });
|
|
51
|
+
}
|
|
52
|
+
// Factory: import a raw 32-byte key (useful for deterministic test fixtures).
|
|
53
|
+
static async fromRawBytes(keyId, rawBytes) {
|
|
54
|
+
const key = await globalThis.crypto.subtle.importKey("raw", new Uint8Array(rawBytes), // CRYPTO_WEBCRYPTO_TYPES_001: ensure ArrayBuffer backing
|
|
55
|
+
{ name: "AES-GCM" }, false, // non-extractable (tighter for imported keys)
|
|
56
|
+
["encrypt", "decrypt"]);
|
|
57
|
+
return new StaticKeyProvider({ keyId, key });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=static-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-key.js","sourceRoot":"","sources":["../../src/crypto/static-key.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,EAAE;AACF,wDAAwD;AACxD,6FAA6F;AAC7F,0DAA0D;AAC1D,EAAE;AACF,mFAAmF;AACnF,mFAAmF;AACnF,gFAAgF;AAChF,iEAAiE;AAIjE,MAAM,OAAO,iBAAiB;IACX,QAAQ,CAAgB;IACxB,QAAQ,CAAqC;IAE9D,mEAAmE;IACnE,0EAA0E;IAC1E,uFAAuF;IACvF,YAAY,OAAsB,EAAE,aAAuC,EAAE;QAC3E,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;QACxB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAwB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QACvE,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;YAC9B,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,MAAM,CAAC,MAAM,CACjB,IAAI,KAAK,CACP,4CAA4C,IAAI,CAAC,KAAK,8EAA8E,CACrI,EACD,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAC7C,CAAC;YACJ,CAAC;YACD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC;IACtB,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAAa;QACxB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;IAED,+EAA+E;IAC/E,6EAA6E;IAC7E,qEAAqE;IACrE,iFAAiF;IACjF,8EAA8E;IAC9E,cAAc,CAAC,UAAyB;QACtC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;YACxC,MAAM,MAAM,CAAC,MAAM,CACjB,IAAI,KAAK,CACP,6DAA6D,UAAU,CAAC,KAAK,0EAA0E,CACxJ,EACD,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAC7C,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,iBAAiB,CAAC,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;IAED,gDAAgD;IAChD,qEAAqE;IACrE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAa;QACjC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CACpD,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,EAChC,IAAI,EAAS,iCAAiC;QAC9C,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;QACF,OAAO,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,8EAA8E;IAC9E,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,KAAa,EAAE,QAAoB;QAC3D,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAClD,KAAK,EACL,IAAI,UAAU,CAAC,QAAQ,CAAC,EAAE,yDAAyD;QACnF,EAAE,IAAI,EAAE,SAAS,EAAE,EACnB,KAAK,EAAQ,8CAA8C;QAC3D,CAAC,SAAS,EAAE,SAAS,CAAC,CACvB,CAAC;QACF,OAAO,IAAI,iBAAiB,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAC/C,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface EncryptedBlob {
|
|
2
|
+
readonly algorithm: "AES-256-GCM";
|
|
3
|
+
readonly keyId: string;
|
|
4
|
+
readonly iv: string;
|
|
5
|
+
readonly ciphertext: string;
|
|
6
|
+
}
|
|
7
|
+
export interface CryptoBoundary {
|
|
8
|
+
encryptJson(value: unknown): Promise<EncryptedBlob>;
|
|
9
|
+
decryptJson(blob: EncryptedBlob): Promise<unknown>;
|
|
10
|
+
encryptBytes(bytes: Uint8Array): Promise<EncryptedBlob>;
|
|
11
|
+
decryptBytes(blob: EncryptedBlob): Promise<Uint8Array>;
|
|
12
|
+
}
|
|
13
|
+
export interface KeyDescriptor {
|
|
14
|
+
readonly keyId: string;
|
|
15
|
+
readonly key: CryptoKey;
|
|
16
|
+
}
|
|
17
|
+
export interface KeyProvider {
|
|
18
|
+
getCurrentKey(): Promise<KeyDescriptor>;
|
|
19
|
+
getKey(keyId: string): Promise<KeyDescriptor | undefined>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Slice-05: CryptoBoundary types.
|
|
2
|
+
// These types define the interface between domain and persistence layers.
|
|
3
|
+
// Domain objects remain plaintext. Only ClaimSerializer (at the boundary) uses these.
|
|
4
|
+
//
|
|
5
|
+
// CRYPTO_BOUNDARY_ONLY_001: only src/crypto/** may import crypto primitives.
|
|
6
|
+
// CRYPTO_KEY_PROVIDER_DI_001: AesGcmCryptoBoundary receives KeyProvider via constructor.
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/crypto/types.ts"],"names":[],"mappings":"AAAA,kCAAkC;AAClC,0EAA0E;AAC1E,sFAAsF;AACtF,EAAE;AACF,6EAA6E;AAC7E,yFAAyF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/** A registry record for a certified trusted data-source institution. */
|
|
2
|
+
export interface TrustedDataSourceEntry {
|
|
3
|
+
/** Stable source identifier, e.g. "cardiologie-klinik-bern". */
|
|
4
|
+
readonly sourceId: string;
|
|
5
|
+
/** Human-readable name for operator reference. */
|
|
6
|
+
readonly name: string;
|
|
7
|
+
/** Write scopes this source is certified for, e.g. ["write:contract.amount"]. */
|
|
8
|
+
readonly allowedScopes: ReadonlyArray<string>;
|
|
9
|
+
/** ID of the certifying authority: "life-as-api-foundation" | "self" | host-defined. */
|
|
10
|
+
readonly certifiedBy: string;
|
|
11
|
+
/** Epoch ms — when this certification was issued. */
|
|
12
|
+
readonly certifiedAt: number;
|
|
13
|
+
/** Epoch ms — instant after which this certification is no longer valid. */
|
|
14
|
+
readonly validUntil: number;
|
|
15
|
+
/**
|
|
16
|
+
* Declared now; cryptographic enforcement (signed proposal verification) is deferred.
|
|
17
|
+
* TRUSTED_DATA_SOURCE_SIGNED_PROPOSALS_DEFERRED_001
|
|
18
|
+
*/
|
|
19
|
+
readonly requiresSignedProposals: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Trust gate for write-proposal disposition. Configured registries determine which
|
|
23
|
+
* proposing institutions may have their proposals auto-accepted (see ProposalPolicy).
|
|
24
|
+
* Implementations must be fail-closed: any exception → treated as untrusted.
|
|
25
|
+
*/
|
|
26
|
+
export interface TrustedDataSourceRegistry {
|
|
27
|
+
/** Returns true iff sourceId is registered, not expired, and certified for scope. */
|
|
28
|
+
isSourceTrusted(sourceId: string, scope: string): Promise<boolean>;
|
|
29
|
+
/** Returns a frozen copy of the entry, or undefined if not registered. */
|
|
30
|
+
getEntry(sourceId: string): Promise<TrustedDataSourceEntry | undefined>;
|
|
31
|
+
}
|
|
32
|
+
/** Development / test implementation of TrustedDataSourceRegistry. */
|
|
33
|
+
export declare class InMemoryTrustedDataSourceRegistry implements TrustedDataSourceRegistry {
|
|
34
|
+
private readonly _entries;
|
|
35
|
+
private readonly _now;
|
|
36
|
+
constructor(opts?: {
|
|
37
|
+
readonly now?: () => number;
|
|
38
|
+
});
|
|
39
|
+
/** Register or replace an entry. Re-registering the same sourceId overwrites. */
|
|
40
|
+
register(entry: TrustedDataSourceEntry): this;
|
|
41
|
+
/**
|
|
42
|
+
* TRUSTED_DATA_SOURCE_REGISTRY_FAIL_CLOSED_001:
|
|
43
|
+
* - Unknown sourceId → false
|
|
44
|
+
* - validUntil not a finite number → false
|
|
45
|
+
* - validUntil <= now (epoch-ms comparison) → false (expired)
|
|
46
|
+
* - scope not exactly in allowedScopes → false
|
|
47
|
+
* - Never throws; caller may treat any exception as untrusted anyway.
|
|
48
|
+
*/
|
|
49
|
+
isSourceTrusted(sourceId: string, scope: string): Promise<boolean>;
|
|
50
|
+
getEntry(sourceId: string): Promise<TrustedDataSourceEntry | undefined>;
|
|
51
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Platform-02 — Trusted Data Source Registry.
|
|
2
|
+
//
|
|
3
|
+
// TRUSTED_DATA_SOURCE_REGISTRY_FAIL_CLOSED_001: unknown source, expired certification,
|
|
4
|
+
// unrecognised scope, or any exception → untrusted. Never fail-open.
|
|
5
|
+
// TRUSTED_DATA_SOURCE_REGISTRY_EXPIRY_ENFORCED_001: validUntil epoch-ms comparison;
|
|
6
|
+
// validUntil <= now is expired.
|
|
7
|
+
// TRUSTED_DATA_SOURCE_SIGNED_PROPOSALS_DEFERRED_001: requiresSignedProposals is declared
|
|
8
|
+
// but cryptographic enforcement is deferred (mirrors
|
|
9
|
+
// TRUSTED_AGENT_REGISTRY_PUBKEY_ENFORCEMENT_DEFERRED_001).
|
|
10
|
+
// TRUSTED_DATA_SOURCE_REGISTRY_INTERFACE_DATASOURCE_MODULE_ONLY_001: this interface is
|
|
11
|
+
// defined exclusively in src/datasource/; production src code imports it type-only
|
|
12
|
+
// except the re-export in src/index.ts and the factory wiring in
|
|
13
|
+
// src/sdk/create-sqlite-life-api.ts.
|
|
14
|
+
// ─── InMemory implementation ─────────────────────────────────────────────────────
|
|
15
|
+
/** Development / test implementation of TrustedDataSourceRegistry. */
|
|
16
|
+
export class InMemoryTrustedDataSourceRegistry {
|
|
17
|
+
_entries = new Map();
|
|
18
|
+
_now;
|
|
19
|
+
constructor(opts) {
|
|
20
|
+
this._now = opts?.now ?? (() => Date.now());
|
|
21
|
+
}
|
|
22
|
+
/** Register or replace an entry. Re-registering the same sourceId overwrites. */
|
|
23
|
+
register(entry) {
|
|
24
|
+
this._entries.set(entry.sourceId, entry);
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* TRUSTED_DATA_SOURCE_REGISTRY_FAIL_CLOSED_001:
|
|
29
|
+
* - Unknown sourceId → false
|
|
30
|
+
* - validUntil not a finite number → false
|
|
31
|
+
* - validUntil <= now (epoch-ms comparison) → false (expired)
|
|
32
|
+
* - scope not exactly in allowedScopes → false
|
|
33
|
+
* - Never throws; caller may treat any exception as untrusted anyway.
|
|
34
|
+
*/
|
|
35
|
+
async isSourceTrusted(sourceId, scope) {
|
|
36
|
+
const entry = this._entries.get(sourceId);
|
|
37
|
+
if (entry === undefined)
|
|
38
|
+
return false;
|
|
39
|
+
// TRUSTED_DATA_SOURCE_REGISTRY_EXPIRY_ENFORCED_001
|
|
40
|
+
if (!Number.isFinite(entry.validUntil))
|
|
41
|
+
return false;
|
|
42
|
+
const nowMs = this._now();
|
|
43
|
+
if (entry.validUntil <= nowMs)
|
|
44
|
+
return false;
|
|
45
|
+
// Scope check: exact match in allowedScopes — no prefix matching.
|
|
46
|
+
if (!entry.allowedScopes.includes(scope))
|
|
47
|
+
return false;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
async getEntry(sourceId) {
|
|
51
|
+
const entry = this._entries.get(sourceId);
|
|
52
|
+
if (entry === undefined)
|
|
53
|
+
return undefined;
|
|
54
|
+
return Object.freeze({ ...entry, allowedScopes: Object.freeze([...entry.allowedScopes]) });
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=trusted-data-source-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted-data-source-registry.js","sourceRoot":"","sources":["../../src/datasource/trusted-data-source-registry.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,uFAAuF;AACvF,uEAAuE;AACvE,oFAAoF;AACpF,kCAAkC;AAClC,yFAAyF;AACzF,uDAAuD;AACvD,6DAA6D;AAC7D,uFAAuF;AACvF,qFAAqF;AACrF,mEAAmE;AACnE,uCAAuC;AAuCvC,oFAAoF;AAEpF,sEAAsE;AACtE,MAAM,OAAO,iCAAiC;IAC3B,QAAQ,GAAG,IAAI,GAAG,EAAkC,CAAC;IACrD,IAAI,CAAe;IAEpC,YAAY,IAAsC;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,iFAAiF;IACjF,QAAQ,CAAC,KAA6B;QACpC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,eAAe,CAAC,QAAgB,EAAE,KAAa;QACnD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAEtC,mDAAmD;QACnD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC;YAAE,OAAO,KAAK,CAAC;QAErD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QAE5C,kEAAkE;QAClE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QAEvD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1C,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC1C,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PersonId, SourceId, ISOTime, AuditId } from "../types/ids.js";
|
|
2
|
+
import type { ClaimPredicate } from "../types/claim.js";
|
|
3
|
+
export declare const ERASURE_TOMBSTONE_PREDICATE: ClaimPredicate;
|
|
4
|
+
export declare const ERASURE_TOMBSTONE_PAYLOAD: {
|
|
5
|
+
type: "string";
|
|
6
|
+
value: "erasure-marker";
|
|
7
|
+
};
|
|
8
|
+
export declare const SYSTEM_ERASURE_SOURCE_ID: SourceId;
|
|
9
|
+
export interface ErasureStatus {
|
|
10
|
+
readonly subject: PersonId;
|
|
11
|
+
readonly recordedAt: ISOTime;
|
|
12
|
+
readonly auditEventId: AuditId;
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Slice-21a: Erasure Tombstone boundary constants and types.
|
|
2
|
+
//
|
|
3
|
+
// ERASURE_TOMBSTONE_PREDICATE_OPEN_UNION_001: "system.erasure_request" is valid as
|
|
4
|
+
// ClaimPredicate via the open extension union (string & Record<never, never>).
|
|
5
|
+
// No TypeScript type change required. No schema migration required.
|
|
6
|
+
// ERASURE_TOMBSTONE_PAYLOAD_NON_SENSITIVE_001: payload is a non-sensitive marker;
|
|
7
|
+
// safe erasure-status APIs derive their response from metadata only.
|
|
8
|
+
// ERASURE_PROOF_IS_TECHNICAL_ONLY_001: ErasureStatus is a technical record within
|
|
9
|
+
// the SDK persistence boundary — not legal proof of deletion from external systems.
|
|
10
|
+
import { asSourceId } from "../types/ids.js";
|
|
11
|
+
export const ERASURE_TOMBSTONE_PREDICATE = "system.erasure_request";
|
|
12
|
+
// Non-sensitive marker payload — encrypted at rest like any other claim.
|
|
13
|
+
// ERASURE_TOMBSTONE_PAYLOAD_NON_SENSITIVE_001
|
|
14
|
+
export const ERASURE_TOMBSTONE_PAYLOAD = {
|
|
15
|
+
type: "string",
|
|
16
|
+
value: "erasure-marker",
|
|
17
|
+
};
|
|
18
|
+
// Stable source ID for tombstone claims — pre-registered in factory initialization.
|
|
19
|
+
export const SYSTEM_ERASURE_SOURCE_ID = asSourceId("src:system:erasure");
|
|
20
|
+
//# sourceMappingURL=tombstone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tombstone.js","sourceRoot":"","sources":["../../src/erasure/tombstone.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,EAAE;AACF,mFAAmF;AACnF,iFAAiF;AACjF,sEAAsE;AACtE,kFAAkF;AAClF,uEAAuE;AACvE,kFAAkF;AAClF,sFAAsF;AAItF,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,MAAM,CAAC,MAAM,2BAA2B,GAAmB,wBAAwB,CAAC;AAEpF,yEAAyE;AACzE,8CAA8C;AAC9C,MAAM,CAAC,MAAM,yBAAyB,GAAG;IACvC,IAAI,EAAG,QAAiB;IACxB,KAAK,EAAE,gBAAyB;CACjC,CAAC;AAEF,oFAAoF;AACpF,MAAM,CAAC,MAAM,wBAAwB,GAAa,UAAU,CAAC,oBAAoB,CAAC,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { EvidenceId, SourceId, ClaimId } from "../types/ids.js";
|
|
2
|
+
import type { OwnerContext, SystemProjectionContext, TestContext } from "../types/access-context.js";
|
|
3
|
+
import type { AppendClaimInput } from "../types/claim.js";
|
|
4
|
+
import type { FactStore } from "../types/fact-store.js";
|
|
5
|
+
import type { EvidenceRef } from "../types/evidence.js";
|
|
6
|
+
import type { Source, SourceKind } from "../types/source.js";
|
|
7
|
+
import type { RawDocumentStore } from "./raw-document-store.js";
|
|
8
|
+
import type { SourceRegistry } from "../source/source-registry.js";
|
|
9
|
+
import type { UnitOfWork } from "../persistence/unit-of-work.js";
|
|
10
|
+
export type EvidenceClaimCreator = OwnerContext | SystemProjectionContext | TestContext;
|
|
11
|
+
export interface CreateClaimFromExistingEvidenceInput {
|
|
12
|
+
readonly evidenceId: EvidenceId;
|
|
13
|
+
readonly sourceId: SourceId;
|
|
14
|
+
readonly claim: Omit<AppendClaimInput, "sourceId">;
|
|
15
|
+
}
|
|
16
|
+
export interface CreateClaimWithNewEvidenceInput {
|
|
17
|
+
readonly document: {
|
|
18
|
+
readonly bytes: Uint8Array;
|
|
19
|
+
readonly mimeType: string;
|
|
20
|
+
readonly label?: string;
|
|
21
|
+
readonly metadata?: Record<string, unknown>;
|
|
22
|
+
};
|
|
23
|
+
readonly source: {
|
|
24
|
+
readonly id: SourceId;
|
|
25
|
+
readonly kind: SourceKind;
|
|
26
|
+
readonly label: string;
|
|
27
|
+
readonly metadata?: Record<string, unknown>;
|
|
28
|
+
};
|
|
29
|
+
readonly claim: Omit<AppendClaimInput, "sourceId">;
|
|
30
|
+
}
|
|
31
|
+
export interface EvidenceBackedClaimResult {
|
|
32
|
+
readonly claimId: ClaimId;
|
|
33
|
+
}
|
|
34
|
+
export interface EvidenceBackedClaimWithNewEvidenceResult {
|
|
35
|
+
readonly evidenceRef: EvidenceRef;
|
|
36
|
+
readonly source: Source;
|
|
37
|
+
readonly claimId: ClaimId;
|
|
38
|
+
}
|
|
39
|
+
export declare class EvidenceBackedClaimCreator {
|
|
40
|
+
private readonly _rawDocumentStore;
|
|
41
|
+
private readonly _sourceRegistry;
|
|
42
|
+
private readonly _factStore;
|
|
43
|
+
private readonly _uow;
|
|
44
|
+
constructor(_rawDocumentStore: RawDocumentStore, _sourceRegistry: SourceRegistry, _factStore: FactStore, _uow: UnitOfWork);
|
|
45
|
+
createClaimFromExistingEvidence(ctx: EvidenceClaimCreator, input: CreateClaimFromExistingEvidenceInput): Promise<EvidenceBackedClaimResult>;
|
|
46
|
+
createClaimWithNewEvidence(ctx: EvidenceClaimCreator, input: CreateClaimWithNewEvidenceInput): Promise<EvidenceBackedClaimWithNewEvidenceResult>;
|
|
47
|
+
private _assertEvidenceClaimCreator;
|
|
48
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// EvidenceBackedClaimCreator — Slice-10.
|
|
2
|
+
//
|
|
3
|
+
// Creates claims whose provenance chain is machine-verifiable:
|
|
4
|
+
// Claim → Source → EvidenceRef → encrypted RawDocument
|
|
5
|
+
//
|
|
6
|
+
// EVIDENCE_BACKED_CLAIM_CREATOR_EXISTS_001: single service owns the provenance chain.
|
|
7
|
+
// EVIDENCE_BACKED_CLAIM_AGENT_DENIED_001: agent + audit contexts are rejected.
|
|
8
|
+
// EVIDENCE_BACKED_CLAIM_APPENDS_THROUGH_SOURCE_AWARE_STORE_001:
|
|
9
|
+
// append goes through FactStore interface (wired as SourceAwareFactStore in production).
|
|
10
|
+
// UNIT_OF_WORK_EVIDENCE_CLAIM_ATOMIC_001:
|
|
11
|
+
// createClaimWithNewEvidence is wrapped in UnitOfWork.run() — document + source + claim
|
|
12
|
+
// are all committed or all rolled back (UNIT_OF_WORK_NO_PARTIAL_DOCUMENT_SOURCE_CLAIM_001).
|
|
13
|
+
//
|
|
14
|
+
// Forbidden imports: no crypto primitives, no concrete FactStore, no contract/consent/proposal.
|
|
15
|
+
// ─── Service ──────────────────────────────────────────────────────────────────
|
|
16
|
+
export class EvidenceBackedClaimCreator {
|
|
17
|
+
_rawDocumentStore;
|
|
18
|
+
_sourceRegistry;
|
|
19
|
+
_factStore;
|
|
20
|
+
_uow;
|
|
21
|
+
constructor(_rawDocumentStore, _sourceRegistry, _factStore, _uow) {
|
|
22
|
+
this._rawDocumentStore = _rawDocumentStore;
|
|
23
|
+
this._sourceRegistry = _sourceRegistry;
|
|
24
|
+
this._factStore = _factStore;
|
|
25
|
+
this._uow = _uow;
|
|
26
|
+
}
|
|
27
|
+
// Append a claim against an already-stored document and already-registered source.
|
|
28
|
+
// Validates the full provenance chain before any write:
|
|
29
|
+
// 1. evidenceId exists in RawDocumentStore
|
|
30
|
+
// 2. sourceId exists in SourceRegistry
|
|
31
|
+
// 3. source.evidenceRef.id === evidenceId
|
|
32
|
+
// 4. factStore.append (wired as SourceAwareFactStore) validates source is active + predicate allowed
|
|
33
|
+
async createClaimFromExistingEvidence(ctx, input) {
|
|
34
|
+
this._assertEvidenceClaimCreator(ctx);
|
|
35
|
+
// EVIDENCE_BACKED_CLAIM_REQUIRES_DOCUMENT_001
|
|
36
|
+
const evidenceRef = this._rawDocumentStore.getEvidenceRef(ctx, input.evidenceId);
|
|
37
|
+
if (evidenceRef === undefined) {
|
|
38
|
+
throw new Error(`EVIDENCE_BACKED_CLAIM_REQUIRES_DOCUMENT_001: evidenceId "${input.evidenceId}" not found in RawDocumentStore`);
|
|
39
|
+
}
|
|
40
|
+
const source = this._sourceRegistry.getSource(ctx, input.sourceId);
|
|
41
|
+
if (source === undefined) {
|
|
42
|
+
throw new Error(`EVIDENCE_BACKED_CLAIM_SOURCE_MATCHES_EVIDENCE_001: sourceId "${input.sourceId}" not found in SourceRegistry`);
|
|
43
|
+
}
|
|
44
|
+
// EVIDENCE_BACKED_CLAIM_REQUIRES_SOURCE_EVIDENCE_REF_001
|
|
45
|
+
if (source.evidenceRef?.id === undefined) {
|
|
46
|
+
throw new Error(`EVIDENCE_BACKED_CLAIM_REQUIRES_SOURCE_EVIDENCE_REF_001: source "${input.sourceId}" ` +
|
|
47
|
+
`has no evidenceRef.id — provenance chain cannot be verified`);
|
|
48
|
+
}
|
|
49
|
+
// EVIDENCE_BACKED_CLAIM_SOURCE_MATCHES_EVIDENCE_001
|
|
50
|
+
if (source.evidenceRef.id !== input.evidenceId) {
|
|
51
|
+
throw new Error(`EVIDENCE_BACKED_CLAIM_SOURCE_MATCHES_EVIDENCE_001: source "${input.sourceId}" ` +
|
|
52
|
+
`evidenceRef.id "${source.evidenceRef.id}" does not match evidenceId "${input.evidenceId}"`);
|
|
53
|
+
}
|
|
54
|
+
// EVIDENCE_BACKED_CLAIM_APPENDS_THROUGH_SOURCE_AWARE_STORE_001:
|
|
55
|
+
// The injected factStore (SourceAwareFactStore in production) enforces:
|
|
56
|
+
// - source is active (SOURCE_INACTIVE_REJECTED_001)
|
|
57
|
+
// - predicate is allowed for source kind (SOURCE_KIND_ALLOWED_PREDICATE_001)
|
|
58
|
+
const claim = { ...input.claim, sourceId: input.sourceId };
|
|
59
|
+
const { claimId } = await this._factStore.append(claim, ctx);
|
|
60
|
+
return { claimId };
|
|
61
|
+
}
|
|
62
|
+
// Store a new raw document, register a new source linked to it, then append a claim.
|
|
63
|
+
// All three steps are wrapped in this._uow.run() — all commit or all roll back.
|
|
64
|
+
// UNIT_OF_WORK_EVIDENCE_CLAIM_ATOMIC_001 / UNIT_OF_WORK_NO_PARTIAL_DOCUMENT_SOURCE_CLAIM_001
|
|
65
|
+
async createClaimWithNewEvidence(ctx, input) {
|
|
66
|
+
this._assertEvidenceClaimCreator(ctx);
|
|
67
|
+
return this._uow.run(async () => {
|
|
68
|
+
// Step 1: persist encrypted raw document.
|
|
69
|
+
const docInput = {
|
|
70
|
+
bytes: input.document.bytes,
|
|
71
|
+
mimeType: input.document.mimeType,
|
|
72
|
+
...(input.document.label !== undefined ? { label: input.document.label } : {}),
|
|
73
|
+
...(input.document.metadata !== undefined ? { metadata: input.document.metadata } : {}),
|
|
74
|
+
};
|
|
75
|
+
const evidenceRef = await this._rawDocumentStore.putDocument(ctx, docInput);
|
|
76
|
+
// Step 2: register source with evidenceRef.id so the chain is machine-verifiable.
|
|
77
|
+
const srcInput = {
|
|
78
|
+
id: input.source.id,
|
|
79
|
+
kind: input.source.kind,
|
|
80
|
+
label: input.source.label,
|
|
81
|
+
evidenceRef: {
|
|
82
|
+
id: evidenceRef.id,
|
|
83
|
+
uri: evidenceRef.uri,
|
|
84
|
+
mimeType: evidenceRef.mimeType,
|
|
85
|
+
encrypted: true,
|
|
86
|
+
},
|
|
87
|
+
...(input.source.metadata !== undefined ? { metadata: input.source.metadata } : {}),
|
|
88
|
+
};
|
|
89
|
+
const source = this._sourceRegistry.registerSource(ctx, srcInput);
|
|
90
|
+
// Step 3: append claim — claim.sourceId is authoritative from source.id, never caller-supplied.
|
|
91
|
+
// EVIDENCE_BACKED_CLAIM_NO_DOCUMENT_EXTRACTION_001: payload comes from caller input only.
|
|
92
|
+
const claim = { ...input.claim, sourceId: source.id };
|
|
93
|
+
const { claimId } = await this._factStore.append(claim, ctx);
|
|
94
|
+
return { evidenceRef, source, claimId };
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
// Runtime guard: mirrors the EvidenceClaimCreator type constraint.
|
|
98
|
+
// Defense-in-depth for callers that cast their way around the type system.
|
|
99
|
+
_assertEvidenceClaimCreator(ctx) {
|
|
100
|
+
const kind = ctx.kind;
|
|
101
|
+
if (kind === "agent" || kind === "audit") {
|
|
102
|
+
throw new Error(`EVIDENCE_BACKED_CLAIM_AGENT_DENIED_001: "${kind}" context cannot create evidence-backed claims ` +
|
|
103
|
+
`— use ProposalQueue for agent-submitted claims`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=evidence-backed-claim-creator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-backed-claim-creator.js","sourceRoot":"","sources":["../../src/evidence/evidence-backed-claim-creator.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,+DAA+D;AAC/D,yDAAyD;AACzD,EAAE;AACF,sFAAsF;AACtF,+EAA+E;AAC/E,gEAAgE;AAChE,2FAA2F;AAC3F,0CAA0C;AAC1C,0FAA0F;AAC1F,8FAA8F;AAC9F,EAAE;AACF,gGAAgG;AA2DhG,iFAAiF;AAEjF,MAAM,OAAO,0BAA0B;IAElB;IACA;IACA;IACA;IAJnB,YACmB,iBAAmC,EACnC,eAAiC,EACjC,UAA4B,EAC5B,IAA6B;QAH7B,sBAAiB,GAAjB,iBAAiB,CAAkB;QACnC,oBAAe,GAAf,eAAe,CAAkB;QACjC,eAAU,GAAV,UAAU,CAAkB;QAC5B,SAAI,GAAJ,IAAI,CAAyB;IAC7C,CAAC;IAEJ,mFAAmF;IACnF,wDAAwD;IACxD,6CAA6C;IAC7C,yCAAyC;IACzC,4CAA4C;IAC5C,uGAAuG;IACvG,KAAK,CAAC,+BAA+B,CACnC,GAA2B,EAC3B,KAA2C;QAE3C,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;QAEtC,8CAA8C;QAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;QACjF,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CACb,4DAA4D,KAAK,CAAC,UAAU,iCAAiC,CAC9G,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;QACnE,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,gEAAgE,KAAK,CAAC,QAAQ,+BAA+B,CAC9G,CAAC;QACJ,CAAC;QAED,yDAAyD;QACzD,IAAI,MAAM,CAAC,WAAW,EAAE,EAAE,KAAK,SAAS,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,mEAAmE,KAAK,CAAC,QAAQ,IAAI;gBACrF,6DAA6D,CAC9D,CAAC;QACJ,CAAC;QAED,oDAAoD;QACpD,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE,KAAK,KAAK,CAAC,UAAU,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CACb,8DAA8D,KAAK,CAAC,QAAQ,IAAI;gBAChF,mBAAmB,MAAM,CAAC,WAAW,CAAC,EAAE,gCAAgC,KAAK,CAAC,UAAU,GAAG,CAC5F,CAAC;QACJ,CAAC;QAED,gEAAgE;QAChE,wEAAwE;QACxE,sDAAsD;QACtD,+EAA+E;QAC/E,MAAM,KAAK,GAAqB,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7E,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7D,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;IAED,qFAAqF;IACrF,gFAAgF;IAChF,6FAA6F;IAC7F,KAAK,CAAC,0BAA0B,CAC9B,GAA2B,EAC3B,KAAsC;QAEtC,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC;QAEtC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE;YAC9B,0CAA0C;YAC1C,MAAM,QAAQ,GAAG;gBACf,KAAK,EAAK,KAAK,CAAC,QAAQ,CAAC,KAAK;gBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ;gBACjC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,KAAQ,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAK,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAI,CAAC,CAAC,EAAE,CAAC;gBACvF,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACxF,CAAC;YACF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAE5E,kFAAkF;YAClF,MAAM,QAAQ,GAAG;gBACf,EAAE,EAAK,KAAK,CAAC,MAAM,CAAC,EAAE;gBACtB,IAAI,EAAG,KAAK,CAAC,MAAM,CAAC,IAAI;gBACxB,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK;gBACzB,WAAW,EAAE;oBACX,EAAE,EAAS,WAAW,CAAC,EAAE;oBACzB,GAAG,EAAQ,WAAW,CAAC,GAAG;oBAC1B,QAAQ,EAAG,WAAW,CAAC,QAAQ;oBAC/B,SAAS,EAAE,IAAa;iBACzB;gBACD,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpF,CAAC;YACF,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;YAElE,gGAAgG;YAChG,0FAA0F;YAC1F,MAAM,KAAK,GAAqB,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;YACxE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YAE7D,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC;IAED,mEAAmE;IACnE,2EAA2E;IACnE,2BAA2B,CAAC,GAAyB;QAC3D,MAAM,IAAI,GAAI,GAAqB,CAAC,IAAI,CAAC;QACzC,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,4CAA4C,IAAI,iDAAiD;gBACjG,gDAAgD,CACjD,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { EvidenceId } from "../types/ids.js";
|
|
2
|
+
import type { AccessContext } from "../types/access-context.js";
|
|
3
|
+
import type { CryptoBoundary, EncryptedBlob } from "../crypto/types.js";
|
|
4
|
+
import type { EvidenceFilter, EvidenceRef, EvidenceWriter, RawDocument, RawDocumentInput } from "../types/evidence.js";
|
|
5
|
+
import type { RawDocumentStore } from "./raw-document-store.js";
|
|
6
|
+
export declare class InMemoryRawDocumentStore implements RawDocumentStore {
|
|
7
|
+
private readonly _crypto;
|
|
8
|
+
private readonly _entries;
|
|
9
|
+
constructor(_crypto: CryptoBoundary);
|
|
10
|
+
putDocument(ctx: EvidenceWriter, input: RawDocumentInput): Promise<EvidenceRef>;
|
|
11
|
+
_uowSnapshot(): Map<EvidenceId, {
|
|
12
|
+
ref: EvidenceRef;
|
|
13
|
+
encryptedBlob: EncryptedBlob;
|
|
14
|
+
createdBy: EvidenceWriter;
|
|
15
|
+
metadata?: Readonly<Record<string, unknown>>;
|
|
16
|
+
}>;
|
|
17
|
+
_uowRestore(snap: Map<EvidenceId, {
|
|
18
|
+
ref: EvidenceRef;
|
|
19
|
+
encryptedBlob: EncryptedBlob;
|
|
20
|
+
createdBy: EvidenceWriter;
|
|
21
|
+
metadata?: Readonly<Record<string, unknown>>;
|
|
22
|
+
}>): void;
|
|
23
|
+
getDocument(ctx: EvidenceWriter, evidenceId: EvidenceId): Promise<RawDocument | undefined>;
|
|
24
|
+
getEvidenceRef(ctx: AccessContext, evidenceId: EvidenceId): EvidenceRef | undefined;
|
|
25
|
+
listEvidenceRefs(ctx: AccessContext, filter?: EvidenceFilter): EvidenceRef[];
|
|
26
|
+
}
|