@domainkit/capsuledb 0.1.2 → 0.9.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/README.md +109 -7
- package/dist/index.d.mts +20 -51
- package/dist/index.mjs +776 -467
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["Error","Service","Error","CredentialCustody.Service","HostBindings.Service","packageJson.version"],"sources":["../package.json","../src/custody.ts","../src/host-bindings.ts","../src/persistence.ts","../src/index.ts"],"sourcesContent":["","import { Context, Effect, Schema } from \"effect\";\nimport type { ManagedDnsConnections } from \"domainkit\";\n\n/** Secret token material; credential expiry remains ordinary lifecycle metadata. */\nexport type Credential = Omit<ManagedDnsConnections.StoredCredential, \"expiresAt\">;\n\nexport class Error extends Schema.TaggedError<Error>()(\"CredentialCustodyError\", {\n message: Schema.String,\n operation: Schema.String,\n retry: Schema.Literals([\"never\", \"after-user-action\", \"safe\", \"unknown\"]),\n}) {}\n\nexport interface Interface {\n readonly open: (ciphertext: string) => Effect.Effect<Credential, Error>;\n readonly seal: (credential: Credential) => Effect.Effect<string, Error>;\n}\n\n/** Host-owned encryption boundary. DomainKit never receives keys or stores plaintext. */\nexport class Service extends Context.Service<Service, Interface>()(\n \"@domainkit/capsuledb/CredentialCustody\",\n) {}\n","import { Context, Effect, Schema } from \"effect\";\n\nexport class Error extends Schema.TaggedError<Error>()(\"HostBindingError\", {\n message: Schema.String,\n operation: Schema.String,\n retry: Schema.Literals([\"never\", \"after-user-action\", \"safe\", \"unknown\"]),\n}) {}\n\nexport interface OwnerReference {\n readonly ownerReference: string;\n}\n\nexport interface DomainReference extends OwnerReference {\n readonly domainReference: string;\n}\n\nexport interface Interface {\n /** Resolve a durable host owner reference without capturing request identity. */\n readonly owner: (ownerId: string) => Effect.Effect<OwnerReference, Error>;\n /** Resolve a host domain reference inside the caller's active transaction context. */\n readonly domain: (input: {\n readonly domain: string;\n readonly ownerId: string;\n }) => Effect.Effect<DomainReference, Error>;\n /** Project an opaque stored owner reference back to DomainKit's semantic owner id. */\n readonly ownerId: (ownerReference: string) => Effect.Effect<string, Error>;\n}\n\n/** Stateless host mapping for tenant/domain foreign-key references. */\nexport class Service extends Context.Service<Service, Interface>()(\n \"@domainkit/capsuledb/HostBindings\",\n) {}\n","import { makeCapsule, makeMigration, sqlMigrationBody } from \"capsuledb\";\nimport { Connection, ManagedDnsConnections } from \"domainkit\";\nimport { Effect, Layer, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport * as SqlError from \"effect/unstable/sql/SqlError\";\n\nimport * as CredentialCustody from \"./custody.ts\";\nimport * as HostBindings from \"./host-bindings.ts\";\n\ntype Authorization = ManagedDnsConnections.Authorization.ProviderAuthorization;\ntype StoredConnection = typeof ManagedDnsConnections.StoredConnection.Type;\ntype DomainAttachment = typeof Connection.DomainAttachment.Type;\n\ninterface StoredAggregate {\n readonly attachments: ReadonlyArray<DomainAttachment>;\n readonly authorization: Authorization;\n readonly connections: ReadonlyArray<StoredConnection>;\n readonly credentialCiphertext: string;\n readonly credentialExpiresAt: Date | null;\n}\n\ninterface AuthorizationRow {\n readonly capability_evidence: unknown;\n readonly capabilities: unknown;\n readonly created_at: Date;\n readonly credential_ciphertext: string | null;\n readonly expires_at: Date | null;\n readonly id: string;\n readonly kind: string;\n readonly provider_context: unknown;\n readonly provider_id: string;\n readonly revocation: unknown;\n readonly scopes: unknown;\n readonly subject_id: string;\n}\n\ninterface ConnectionRow {\n readonly authorization_id: string;\n readonly created_at: Date;\n readonly id: string;\n readonly organization_id: string;\n}\n\ninterface AttachmentRow {\n readonly connection_id: string;\n readonly created_at: Date;\n readonly id: string;\n readonly provider_account_id: string;\n readonly provider_target_context: unknown;\n readonly provider_zone_id: string;\n readonly provider_zone_name: string;\n}\n\nconst AttachmentContext = Schema.Struct({\n version: Schema.Literal(\"domainkit.attachment.v1\"),\n value: Schema.Struct({\n accountKind: Schema.NullOr(Schema.Literals([\"account\", \"personal\", \"team\"])),\n domain: Schema.String,\n evidence: Schema.optionalKey(Connection.ProviderTargetEvidence),\n }),\n});\n\nconst storageError = (\n operation: string,\n message: string,\n retry: \"never\" | \"after-user-action\" | \"safe\" | \"unknown\" = \"unknown\",\n) =>\n new ManagedDnsConnections.Error({\n category: \"storage\",\n message,\n operation,\n retry,\n });\n\nconst missing = (operation: string, message: string) => storageError(operation, message, \"never\");\nconst conflict = (operation: string, message: string) =>\n storageError(operation, message, \"after-user-action\");\n\nconst sqlErrorMessage = (error: SqlError.SqlError): string =>\n error.reason.cause instanceof Error\n ? `${error.reason._tag}: ${error.reason.cause.message}`\n : `${error.reason._tag}: ${error.reason.message ?? String(error.reason.cause)}`;\n\nconst mapCapabilityError = (\n operation: string,\n error: {\n readonly message: string;\n readonly retry: \"never\" | \"after-user-action\" | \"safe\" | \"unknown\";\n },\n) => storageError(operation, error.message, error.retry);\n\nconst mapSql = <A, E, R>(\n operation: string,\n effect: Effect.Effect<A, E, R>,\n): Effect.Effect<A, Exclude<E, SqlError.SqlError> | ManagedDnsConnections.Error, R> =>\n // SAFETY: the runtime guard maps every SqlError and re-fails every other E unchanged.\n Effect.matchEffect(effect, {\n onFailure: (error) => {\n const mapped: E | ManagedDnsConnections.Error = SqlError.isSqlError(error)\n ? storageError(operation, sqlErrorMessage(error), \"unknown\")\n : error;\n return Effect.fail(mapped);\n },\n onSuccess: Effect.succeed,\n }) as Effect.Effect<A, Exclude<E, SqlError.SqlError> | ManagedDnsConnections.Error, R>;\n\nconst sameAttachment = (left: DomainAttachment, right: DomainAttachment): boolean =>\n left.connectionId === right.connectionId &&\n left.domain === right.domain &&\n left.target.accountId === right.target.accountId &&\n left.target.accountKind === right.target.accountKind &&\n left.target.zoneId === right.target.zoneId &&\n left.target.zoneName === right.target.zoneName;\n\nconst decodeAuthorization = Effect.fn(\"CapsuleManagedDnsConnections.decodeAuthorization\")(\n function* (row: AuthorizationRow) {\n if (row.credential_ciphertext === null) {\n return yield* Effect.fail(\n missing(\"decodeAuthorization\", `Authorization ${row.id} has no credential ciphertext`),\n );\n }\n const authorization = yield* Schema.decodeUnknownEffect(\n ManagedDnsConnections.Authorization.Schema,\n )({\n authorizedById: row.subject_id,\n capabilityEvidence: row.capability_evidence,\n createdAt: row.created_at.toISOString(),\n id: row.id,\n method: row.kind,\n providerContext: row.provider_context,\n providerId: row.provider_id,\n requiredCapabilities: row.capabilities,\n revocation: row.revocation,\n scopes: row.scopes,\n }).pipe(\n Effect.mapError((error) =>\n missing(\"decodeAuthorization\", `Authorization ${row.id} is invalid: ${error.message}`),\n ),\n );\n return {\n authorization,\n credentialCiphertext: row.credential_ciphertext,\n credentialExpiresAt: row.expires_at,\n };\n },\n);\n\nconst decodeAttachment = Effect.fn(\"CapsuleManagedDnsConnections.decodeAttachment\")(function* (\n row: AttachmentRow,\n) {\n const context = yield* Schema.decodeUnknownEffect(AttachmentContext)(\n row.provider_target_context,\n ).pipe(\n Effect.mapError((error) =>\n missing(\"decodeAttachment\", `Attachment ${row.id} context is invalid: ${error.message}`),\n ),\n );\n return yield* Schema.decodeUnknownEffect(Connection.DomainAttachment)({\n connectionId: row.connection_id,\n createdAt: row.created_at.toISOString(),\n domain: context.value.domain,\n id: row.id,\n target: {\n accountId: row.provider_account_id,\n accountKind: context.value.accountKind,\n ...(context.value.evidence === undefined ? {} : { evidence: context.value.evidence }),\n zoneId: row.provider_zone_id,\n zoneName: row.provider_zone_name,\n },\n }).pipe(\n Effect.mapError((error) =>\n missing(\"decodeAttachment\", `Attachment ${row.id} is invalid: ${error.message}`),\n ),\n );\n});\n\nconst encodeAuthorization = Effect.fn(\"CapsuleManagedDnsConnections.encodeAuthorization\")(\n function* (authorization: Authorization) {\n return yield* Schema.encodeUnknownEffect(ManagedDnsConnections.Authorization.Schema)(\n authorization,\n ).pipe(\n Effect.mapError((error) =>\n conflict(\"encodeAuthorization\", `Authorization cannot be encoded: ${error.message}`),\n ),\n );\n },\n);\n\nconst loadAggregate = Effect.fn(\"CapsuleManagedDnsConnections.loadAggregate\")(function* (\n sql: SqlClient.SqlClient,\n bindings: HostBindings.Interface,\n authorizationId: string,\n lock: \"share\" | \"update\" = \"share\",\n) {\n const lockClause = lock === \"update\" ? \"FOR UPDATE\" : \"FOR SHARE\";\n const authorizationRows = yield* sql.unsafe<AuthorizationRow>(\n `SELECT id, provider_id, subject_id, kind, capabilities, capability_evidence, scopes,\n provider_context, revocation, credential_ciphertext, expires_at, created_at\n FROM domain_provider_authorizations WHERE id = $1 ${lockClause}`,\n [authorizationId],\n );\n const row = authorizationRows[0];\n if (row === undefined) return null;\n const decoded = yield* decodeAuthorization(row);\n const connectionRows = yield* sql<ConnectionRow>`SELECT id, organization_id, authorization_id,\n created_at FROM organization_domain_provider_connections\n WHERE authorization_id = ${authorizationId} ORDER BY id`;\n const connections = yield* Effect.forEach(connectionRows, (connection) =>\n bindings.ownerId(connection.organization_id).pipe(\n Effect.mapError((error) => mapCapabilityError(\"loadAggregate\", error)),\n Effect.map(\n (ownerId) =>\n ({\n authorizationId: connection.authorization_id,\n createdAt: connection.created_at,\n id: connection.id,\n method: decoded.authorization.method,\n ownerId,\n providerId: decoded.authorization.providerId,\n }) satisfies StoredConnection,\n ),\n ),\n );\n const attachmentRows = yield* sql<AttachmentRow>`SELECT a.id, a.connection_id,\n a.provider_account_id, a.provider_zone_id, a.provider_zone_name,\n a.provider_target_context, a.created_at\n FROM domain_provider_attachments a\n JOIN organization_domain_provider_connections c ON c.id = a.connection_id\n WHERE c.authorization_id = ${authorizationId} ORDER BY a.id`;\n const attachments = yield* Effect.forEach(attachmentRows, decodeAttachment);\n return {\n attachments,\n authorization: decoded.authorization,\n connections,\n credentialCiphertext: decoded.credentialCiphertext,\n credentialExpiresAt: decoded.credentialExpiresAt,\n } satisfies StoredAggregate;\n});\n\nconst authorizationIdForConnection = Effect.fn(\n \"CapsuleManagedDnsConnections.authorizationIdForConnection\",\n)(function* (sql: SqlClient.SqlClient, connectionId: string) {\n const rows = yield* sql<{ readonly authorization_id: string }>`SELECT authorization_id\n FROM organization_domain_provider_connections WHERE id = ${connectionId}`;\n return rows[0]?.authorization_id ?? null;\n});\n\nconst authorizationIdForAttachment = Effect.fn(\n \"CapsuleManagedDnsConnections.authorizationIdForAttachment\",\n)(function* (sql: SqlClient.SqlClient, attachmentId: string) {\n const rows = yield* sql<{ readonly authorization_id: string }>`SELECT c.authorization_id\n FROM domain_provider_attachments a\n JOIN organization_domain_provider_connections c ON c.id = a.connection_id\n WHERE a.id = ${attachmentId}`;\n return rows[0]?.authorization_id ?? null;\n});\n\nconst openAggregate = Effect.fn(\"CapsuleManagedDnsConnections.openAggregate\")(function* (\n custody: CredentialCustody.Interface,\n aggregate: StoredAggregate,\n) {\n const opened = yield* custody\n .open(aggregate.credentialCiphertext)\n .pipe(Effect.mapError((error) => mapCapabilityError(\"openCredential\", error)));\n const credential = { ...opened, expiresAt: aggregate.credentialExpiresAt };\n return {\n attachments: aggregate.attachments,\n authorization: aggregate.authorization,\n connections: aggregate.connections,\n credential,\n } satisfies ManagedDnsConnections.Aggregate;\n});\n\nconst projectConnection = Effect.fn(\"CapsuleManagedDnsConnections.projectConnection\")(function* (\n custody: CredentialCustody.Interface,\n aggregate: StoredAggregate,\n connection: StoredConnection,\n authorization: Authorization = aggregate.authorization,\n) {\n const opened = yield* openAggregate(custody, aggregate);\n return Connection.project(connection, authorization, opened.credential);\n});\n\nconst writeAuthorization = Effect.fn(\"CapsuleManagedDnsConnections.writeAuthorization\")(function* (\n sql: SqlClient.SqlClient,\n authorization: Authorization,\n credentialCiphertext: string,\n credentialExpiresAt: Date | null,\n) {\n const encoded = yield* encodeAuthorization(authorization);\n yield* sql`INSERT INTO domain_provider_authorizations (\n id, provider_id, account_id, subject_id, kind, capabilities, capability_evidence, scopes,\n provider_context, revocation, credential_ciphertext, expires_at, created_at, updated_at\n ) VALUES (\n ${authorization.id}, ${authorization.providerId}, NULL, ${authorization.authorizedById},\n ${authorization.method}, ${JSON.stringify(encoded.requiredCapabilities)}::jsonb,\n ${JSON.stringify(encoded.capabilityEvidence)}::jsonb,\n ${JSON.stringify(encoded.scopes)}::jsonb, ${JSON.stringify(encoded.providerContext)}::jsonb,\n ${JSON.stringify(encoded.revocation)}::jsonb,\n ${credentialCiphertext}, ${credentialExpiresAt}, ${authorization.createdAt}, NOW()\n ) ON CONFLICT (id) DO UPDATE SET\n provider_id = EXCLUDED.provider_id,\n subject_id = EXCLUDED.subject_id,\n kind = EXCLUDED.kind,\n capabilities = EXCLUDED.capabilities,\n capability_evidence = EXCLUDED.capability_evidence,\n scopes = EXCLUDED.scopes,\n provider_context = EXCLUDED.provider_context,\n revocation = EXCLUDED.revocation,\n credential_ciphertext = EXCLUDED.credential_ciphertext,\n expires_at = EXCLUDED.expires_at,\n updated_at = NOW()`;\n});\n\nconst makeRepository = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n const custody = yield* CredentialCustody.Service;\n const bindings = yield* HostBindings.Service;\n\n const withRevocationLock = <A, E, R>(\n operation: string,\n authorizationId: string,\n effect: Effect.Effect<A, E, R>,\n ) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const rows = yield* sql<{ readonly acquired: boolean }>`\n SELECT pg_try_advisory_xact_lock(hashtextextended(${authorizationId}, 0)) AS acquired`;\n if (rows[0]?.acquired !== true)\n return yield* Effect.fail(\n storageError(operation, \"Provider revocation is already in progress\", \"safe\"),\n );\n return yield* effect;\n }),\n );\n\n const getStored = (authorizationId: string, lock: \"share\" | \"update\" = \"share\") =>\n loadAggregate(sql, bindings, authorizationId, lock);\n\n const get = (authorizationId: string) =>\n mapSql(\n \"get\",\n sql\n .withTransaction(getStored(authorizationId))\n .pipe(\n Effect.flatMap((aggregate) =>\n aggregate === null ? Effect.succeed(null) : openAggregate(custody, aggregate),\n ),\n ),\n );\n\n const getByConnectionId = (connectionId: string) =>\n mapSql(\n \"getByConnectionId\",\n sql\n .withTransaction(\n Effect.gen(function* () {\n const authorizationId = yield* authorizationIdForConnection(sql, connectionId);\n if (authorizationId === null) return null;\n const aggregate = yield* getStored(authorizationId);\n if (\n aggregate === null ||\n !aggregate.connections.some((connection) => connection.id === connectionId)\n )\n return null;\n return aggregate;\n }),\n )\n .pipe(\n Effect.flatMap((aggregate) =>\n aggregate === null ? Effect.succeed(null) : openAggregate(custody, aggregate),\n ),\n ),\n );\n\n const service: ManagedDnsConnections.Interface = ManagedDnsConnections.Service.of({\n attach: (input) =>\n mapSql(\n \"attach\",\n sql.withTransaction(\n Effect.gen(function* () {\n const authorizationId = yield* authorizationIdForConnection(sql, input.connectionId);\n if (authorizationId === null)\n return yield* Effect.fail(missing(\"attach\", \"Provider connection does not exist\"));\n const aggregate = yield* getStored(authorizationId, \"update\");\n if (aggregate === null)\n return yield* Effect.fail(missing(\"attach\", \"Provider authorization does not exist\"));\n const connection = aggregate.connections.find(\n (candidate) =>\n candidate.id === input.connectionId && candidate.ownerId === input.ownerId,\n );\n if (connection === undefined)\n return yield* Effect.fail(\n missing(\"attach\", \"Provider connection does not belong to this owner\"),\n );\n if (aggregate.authorization.revocation._tag === \"Pending\")\n return yield* Effect.fail(\n conflict(\"attach\", \"Provider authorization is awaiting revocation recovery\"),\n );\n if (input.attachment.connectionId !== input.connectionId)\n return yield* Effect.fail(\n conflict(\"attach\", \"Domain attachment targets another connection\"),\n );\n const existing = aggregate.attachments.find(({ id }) => id === input.attachment.id);\n if (existing !== undefined) {\n if (!sameAttachment(existing, input.attachment))\n return yield* Effect.fail(\n conflict(\"attach\", \"Domain attachment id is already in use\"),\n );\n return {\n attachment: existing,\n connection: yield* projectConnection(custody, aggregate, connection),\n };\n }\n const reference = yield* bindings\n .domain({ domain: input.attachment.domain, ownerId: input.ownerId })\n .pipe(Effect.mapError((error) => mapCapabilityError(\"attach\", error)));\n const context = {\n version: \"domainkit.attachment.v1\" as const,\n value: {\n accountKind: input.attachment.target.accountKind,\n domain: input.attachment.domain,\n ...(input.attachment.target.evidence === undefined\n ? {}\n : { evidence: input.attachment.target.evidence }),\n },\n };\n yield* sql`INSERT INTO domain_provider_attachments (\n id, organization_id, connection_id, domain_id, provider_account_id,\n provider_zone_id, provider_zone_name, provider_target_context, created_at, updated_at\n ) VALUES (\n ${input.attachment.id}, ${reference.ownerReference}, ${input.connectionId},\n ${reference.domainReference}, ${input.attachment.target.accountId},\n ${input.attachment.target.zoneId}, ${input.attachment.target.zoneName},\n ${JSON.stringify(context)}::jsonb,\n ${input.attachment.createdAt}, NOW()\n )`;\n return {\n attachment: input.attachment,\n connection: yield* projectConnection(custody, aggregate, connection),\n };\n }),\n ),\n ),\n connect: (input) =>\n custody.seal(input.credential).pipe(\n Effect.mapError((error) => mapCapabilityError(\"connect\", error)),\n Effect.flatMap((credentialCiphertext) =>\n mapSql(\n \"connect\",\n sql.withTransaction(\n Effect.gen(function* () {\n yield* sql`SELECT pg_advisory_xact_lock(hashtextextended(${input.authorization.id}, 0))`;\n const current = yield* getStored(input.authorization.id, \"update\");\n if (\n current?.authorization.revocation._tag === \"Pending\" ||\n (input.expectedAuthorizationId !== undefined && current === null)\n )\n return yield* Effect.fail(\n conflict(\n \"connect\",\n current === null\n ? \"Provider authorization no longer exists\"\n : \"Provider authorization is awaiting revocation recovery\",\n ),\n );\n if (\n input.authorization.id !== input.connection.authorizationId ||\n input.authorization.providerId !== input.connection.providerId ||\n input.authorization.method !== input.connection.method\n )\n return yield* Effect.fail(\n conflict(\"connect\", \"Connection does not match its authorization\"),\n );\n const existingConnection = current?.connections.find(\n ({ ownerId }) => ownerId === input.connection.ownerId,\n );\n if (\n input.expectedConnectionId !== undefined &&\n existingConnection?.id !== input.expectedConnectionId\n )\n return yield* Effect.fail(\n conflict(\"connect\", \"Organization connection changed during reconnect\"),\n );\n yield* writeAuthorization(\n sql,\n input.authorization,\n credentialCiphertext,\n input.credential.expiresAt,\n );\n if (existingConnection === undefined) {\n const reference = yield* bindings\n .owner(input.connection.ownerId)\n .pipe(Effect.mapError((error) => mapCapabilityError(\"connect\", error)));\n yield* sql`INSERT INTO organization_domain_provider_connections (\n id, organization_id, authorization_id, created_at, updated_at\n ) VALUES (\n ${input.connection.id}, ${reference.ownerReference},\n ${input.authorization.id}, ${input.connection.createdAt}, NOW()\n )`;\n }\n const stored = yield* getStored(input.authorization.id, \"update\");\n return (\n stored ?? (yield* Effect.fail(missing(\"connect\", \"Authorization write vanished\")))\n );\n }),\n ),\n ),\n ),\n Effect.flatMap((aggregate) => openAggregate(custody, aggregate)),\n ),\n detach: ({ attachmentId, ownerId }) =>\n mapSql(\n \"detach\",\n sql.withTransaction(\n Effect.gen(function* () {\n const authorizationId = yield* authorizationIdForAttachment(sql, attachmentId);\n if (authorizationId === null)\n return yield* Effect.fail(missing(\"detach\", \"Domain attachment does not exist\"));\n const aggregate = yield* getStored(authorizationId, \"update\");\n const attachment = aggregate?.attachments.find(({ id }) => id === attachmentId);\n if (aggregate === null || attachment === undefined)\n return yield* Effect.fail(missing(\"detach\", \"Domain attachment does not exist\"));\n const connection = aggregate.connections.find(\n ({ id, ownerId: candidate }) =>\n id === attachment.connectionId && candidate === ownerId,\n );\n if (connection === undefined)\n return yield* Effect.fail(\n missing(\"detach\", \"Domain attachment does not belong to this owner\"),\n );\n yield* sql`DELETE FROM domain_provider_attachments WHERE id = ${attachmentId}`;\n return {\n attachment,\n connection: yield* projectConnection(custody, aggregate, connection),\n remainingAttachments: aggregate.attachments.filter(\n ({ connectionId, id }) => connectionId === connection.id && id !== attachmentId,\n ).length,\n };\n }),\n ),\n ),\n disconnect: <E>({\n connectionId,\n ownerId,\n revoke,\n }: {\n readonly connectionId: string;\n readonly ownerId: string;\n readonly revoke: (authorization: Authorization) => Effect.Effect<void, E>;\n }) =>\n mapSql(\n \"disconnect\",\n sql\n .withTransaction(\n Effect.gen(function* () {\n const authorizationId = yield* authorizationIdForConnection(sql, connectionId);\n if (authorizationId === null)\n return yield* Effect.fail(\n missing(\"disconnect\", \"Provider connection does not exist\"),\n );\n const aggregate = yield* getStored(authorizationId, \"update\");\n const connection = aggregate?.connections.find(\n ({ id, ownerId: candidate }) => id === connectionId && candidate === ownerId,\n );\n if (aggregate === null || connection === undefined)\n return yield* Effect.fail(\n missing(\"disconnect\", \"Provider connection does not belong to this owner\"),\n );\n if (aggregate.attachments.some(({ connectionId: id }) => id === connectionId))\n return yield* Effect.fail(\n conflict(\n \"disconnect\",\n \"Detach all organization domains before disconnecting the provider\",\n ),\n );\n if (aggregate.connections.length > 1) {\n yield* sql`DELETE FROM organization_domain_provider_connections\n WHERE id = ${connectionId}`;\n return {\n _tag: \"Disconnected\" as const,\n connection: yield* projectConnection(custody, aggregate, connection),\n remainingConnections: aggregate.connections.length - 1,\n };\n }\n if (aggregate.authorization.revocation._tag === \"Pending\")\n return yield* Effect.fail(\n conflict(\"disconnect\", \"Provider authorization is awaiting revocation recovery\"),\n );\n const pending: Authorization = {\n ...aggregate.authorization,\n revocation: { _tag: \"Pending\", requestedAt: new Date() },\n };\n yield* writeAuthorization(\n sql,\n pending,\n aggregate.credentialCiphertext,\n aggregate.credentialExpiresAt,\n );\n return {\n _tag: \"Prepared\" as const,\n authorization: pending,\n connection: yield* projectConnection(custody, aggregate, connection, pending),\n };\n }),\n )\n .pipe(\n Effect.flatMap((prepared) => {\n if (prepared._tag === \"Disconnected\") {\n const result: ManagedDnsConnections.DisconnectResult = {\n connection: prepared.connection,\n remainingConnections: prepared.remainingConnections,\n revokedAuthorization: false,\n };\n return Effect.succeed(result);\n }\n const result: ManagedDnsConnections.DisconnectResult = {\n connection: prepared.connection,\n remainingConnections: 0,\n revokedAuthorization: true,\n };\n return withRevocationLock(\n \"disconnect\",\n prepared.authorization.id,\n getStored(prepared.authorization.id, \"update\").pipe(\n Effect.flatMap((current) => {\n if (current?.authorization.revocation._tag !== \"Pending\")\n return Effect.fail(\n conflict(\"disconnect\", \"Revocation state changed before provider call\"),\n );\n return revoke(current.authorization).pipe(\n Effect.andThen(\n Effect.gen(function* () {\n const aggregate = yield* getStored(prepared.authorization.id, \"update\");\n if (aggregate?.authorization.revocation._tag !== \"Pending\")\n return yield* Effect.fail(\n conflict(\"disconnect\", \"Revocation state changed before completion\"),\n );\n yield* sql`DELETE FROM domain_provider_attachments WHERE connection_id IN\n (SELECT id FROM organization_domain_provider_connections\n WHERE authorization_id = ${prepared.authorization.id})`;\n yield* sql`DELETE FROM organization_domain_provider_connections\n WHERE authorization_id = ${prepared.authorization.id}`;\n yield* sql`DELETE FROM domain_provider_authorizations\n WHERE id = ${prepared.authorization.id}`;\n }),\n ),\n Effect.as(result),\n );\n }),\n ),\n );\n }),\n ),\n ),\n findConnection: (ownerId, authorizationId) =>\n get(authorizationId).pipe(\n Effect.map(\n (aggregate) =>\n aggregate?.connections.find((connection) => connection.ownerId === ownerId) ?? null,\n ),\n ),\n get,\n getAttachment: (attachmentId) =>\n mapSql(\n \"getAttachment\",\n sql.withTransaction(\n Effect.gen(function* () {\n const authorizationId = yield* authorizationIdForAttachment(sql, attachmentId);\n if (authorizationId === null) return null;\n const aggregate = yield* getStored(authorizationId);\n return aggregate?.attachments.find(({ id }) => id === attachmentId) ?? null;\n }),\n ),\n ),\n getByConnectionId,\n listAttachments: (connectionId, ownerId) =>\n getByConnectionId(connectionId).pipe(\n Effect.flatMap((aggregate) => {\n if (aggregate === null)\n return Effect.fail(missing(\"listAttachments\", \"Provider connection does not exist\"));\n if (\n !aggregate.connections.some(\n (connection) => connection.id === connectionId && connection.ownerId === ownerId,\n )\n )\n return Effect.fail(\n missing(\"listAttachments\", \"Provider connection does not belong to this owner\"),\n );\n return Effect.succeed(\n aggregate.attachments.filter((attachment) => attachment.connectionId === connectionId),\n );\n }),\n ),\n promoteEvidence: (authorizationId, evidence) =>\n mapSql(\n \"promoteEvidence\",\n sql.withTransaction(\n Effect.gen(function* () {\n const aggregate = yield* getStored(authorizationId, \"update\");\n if (aggregate === null)\n return yield* Effect.fail(\n missing(\"promoteEvidence\", \"Provider authorization does not exist\"),\n );\n const byCapability = new Map(\n aggregate.authorization.capabilityEvidence.map((item) => [item.capability, item]),\n );\n for (const item of evidence) byCapability.set(item.capability, item);\n yield* writeAuthorization(\n sql,\n {\n ...aggregate.authorization,\n capabilityEvidence: [...byCapability.values()],\n },\n aggregate.credentialCiphertext,\n aggregate.credentialExpiresAt,\n );\n return (\n (yield* getStored(authorizationId, \"update\")) ??\n (yield* Effect.fail(missing(\"promoteEvidence\", \"Authorization write vanished\")))\n );\n }),\n ),\n ).pipe(Effect.flatMap((aggregate) => openAggregate(custody, aggregate))),\n recover: ({ authorizationId, revoke }) =>\n mapSql(\n \"recover\",\n withRevocationLock(\n \"recover\",\n authorizationId,\n getStored(authorizationId, \"update\").pipe(\n Effect.flatMap((aggregate) =>\n Effect.gen(function* () {\n if (aggregate === null)\n return yield* Effect.fail(\n missing(\"recover\", \"Provider authorization does not exist\"),\n );\n if (aggregate.authorization.revocation._tag !== \"Pending\")\n return yield* Effect.fail(\n missing(\"recover\", \"Provider authorization is not awaiting revocation\"),\n );\n const connection = aggregate.connections[0];\n if (connection === undefined)\n return yield* Effect.fail(\n missing(\"recover\", \"Pending authorization has no connection\"),\n );\n const projected = yield* projectConnection(custody, aggregate, connection);\n return yield* revoke(aggregate.authorization).pipe(\n Effect.andThen(\n Effect.gen(function* () {\n const current = yield* getStored(authorizationId, \"update\");\n if (current?.authorization.revocation._tag !== \"Pending\")\n return yield* Effect.fail(\n conflict(\"recover\", \"Revocation state changed before completion\"),\n );\n yield* sql`DELETE FROM domain_provider_attachments WHERE connection_id IN\n (SELECT id FROM organization_domain_provider_connections\n WHERE authorization_id = ${authorizationId})`;\n yield* sql`DELETE FROM organization_domain_provider_connections\n WHERE authorization_id = ${authorizationId}`;\n yield* sql`DELETE FROM domain_provider_authorizations WHERE id = ${authorizationId}`;\n }),\n ),\n Effect.as({\n connection: projected,\n remainingConnections: 0,\n revokedAuthorization: true as const,\n }),\n );\n }),\n ),\n ),\n ),\n ),\n rotate: (authorizationId, credential) =>\n custody.seal(credential).pipe(\n Effect.mapError((error) => mapCapabilityError(\"rotate\", error)),\n Effect.flatMap((credentialCiphertext) =>\n mapSql(\n \"rotate\",\n sql.withTransaction(\n Effect.gen(function* () {\n const aggregate = yield* getStored(authorizationId, \"update\");\n if (aggregate === null)\n return yield* Effect.fail(\n missing(\"rotate\", \"Provider authorization does not exist\"),\n );\n yield* writeAuthorization(\n sql,\n aggregate.authorization,\n credentialCiphertext,\n credential.expiresAt,\n );\n return (\n (yield* getStored(authorizationId, \"update\")) ??\n (yield* Effect.fail(missing(\"rotate\", \"Authorization write vanished\")))\n );\n }),\n ),\n ),\n ),\n Effect.flatMap((aggregate) => openAggregate(custody, aggregate)),\n ),\n });\n\n return service;\n});\n\nconst migration = makeMigration({\n id: 1,\n name: \"adopt-authorization-lifecycle\",\n risk: \"additive\",\n providers: {\n Postgres: sqlMigrationBody([\n `CREATE TABLE IF NOT EXISTS domain_provider_authorizations (\n id TEXT PRIMARY KEY NOT NULL,\n provider_id TEXT NOT NULL,\n account_id TEXT,\n subject_id TEXT NOT NULL,\n kind TEXT NOT NULL,\n capabilities JSONB NOT NULL,\n capability_evidence JSONB NOT NULL,\n scopes JSONB NOT NULL,\n provider_context JSONB NOT NULL,\n revocation JSONB NOT NULL,\n credential_ciphertext TEXT,\n expires_at TIMESTAMPTZ,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n )`,\n `ALTER TABLE domain_provider_authorizations\n DROP CONSTRAINT IF EXISTS uq_domain_provider_authorizations_provider_account`,\n `ALTER TABLE domain_provider_authorizations ALTER COLUMN account_id DROP NOT NULL`,\n `CREATE TABLE IF NOT EXISTS organization_domain_provider_connections (\n id TEXT PRIMARY KEY NOT NULL,\n organization_id TEXT NOT NULL,\n authorization_id TEXT NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n CONSTRAINT uq_organization_domain_provider_connections_org_authorization\n UNIQUE (organization_id, authorization_id),\n CONSTRAINT uq_organization_domain_provider_connections_id_org\n UNIQUE (id, organization_id)\n )`,\n `CREATE INDEX IF NOT EXISTS idx_organization_domain_provider_connections_authorization\n ON organization_domain_provider_connections (authorization_id)`,\n `DO $$ BEGIN\n IF to_regclass('domain_connections') IS NOT NULL THEN\n INSERT INTO organization_domain_provider_connections (\n id, organization_id, authorization_id, created_at, updated_at\n ) SELECT id, organization_id, authorization_id, created_at, updated_at\n FROM domain_connections ON CONFLICT DO NOTHING;\n END IF;\n END $$`,\n `CREATE TABLE IF NOT EXISTS domain_provider_attachments (\n id TEXT PRIMARY KEY NOT NULL,\n organization_id TEXT NOT NULL,\n connection_id TEXT NOT NULL,\n domain_id TEXT NOT NULL,\n provider_account_id TEXT NOT NULL,\n provider_zone_id TEXT NOT NULL,\n provider_zone_name TEXT NOT NULL,\n provider_target_context JSONB NOT NULL,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n CONSTRAINT uq_domain_provider_attachments_org_domain UNIQUE (organization_id, domain_id),\n CONSTRAINT uq_domain_provider_attachments_connection_domain UNIQUE (connection_id, domain_id)\n )`,\n `CREATE INDEX IF NOT EXISTS idx_domain_provider_attachments_connection\n ON domain_provider_attachments (connection_id)`,\n `DO $$ BEGIN\n IF EXISTS (SELECT 1 FROM domain_provider_authorizations WHERE credential_ciphertext IS NULL)\n THEN RAISE EXCEPTION 'DomainKit adoption requires encrypted credential ciphertext';\n END IF;\n IF EXISTS (\n SELECT 1 FROM domain_provider_attachments\n WHERE provider_target_context #>> '{value,domain}' IS NULL\n ) THEN RAISE EXCEPTION 'DomainKit adoption requires semantic attachment domains';\n END IF;\n END $$`,\n ]),\n },\n});\n\n/** PostgreSQL-only authorization lifecycle capsule. The host must prepare its registry at startup. */\nexport const capsule = Effect.gen(function* () {\n const definedMigration = yield* migration;\n return yield* makeCapsule({\n id: \"domainkit.authorization-lifecycle\",\n migrations: [definedMigration],\n layer: Layer.effect(ManagedDnsConnections.Service, makeRepository),\n });\n});\n","import packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const VERSION = packageJson.version;\n\nexport * as CredentialCustody from \"./custody.ts\";\nexport * as HostBindings from \"./host-bindings.ts\";\nexport { capsule } from \"./persistence.ts\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["Schema","make","make","makeTables","makeService","packageJson.version"],"sources":["../package.json","../src/internal/storage.ts","../src/internal/tables.ts","../src/capsule.ts","../src/PgStorage.ts","../src/index.ts"],"sourcesContent":["","/**\n * `Storage.Interface` on PostgreSQL.\n *\n * Every method reads `Principal` and filters by `owner_id`, so a row belonging to another tenant\n * is indistinguishable from a row that does not exist. Aggregate transitions run inside one\n * transaction over a `FOR UPDATE` row, single-flight guards use a session-level advisory lock on a\n * reserved connection, and revocation is two-phase: mark `pending`, call the provider outside any\n * transaction, then delete.\n *\n * Storage never sees plaintext. `Connect` seals a credential through `Custody` before it reaches\n * `upsert` or `rotate`, so this module only ever moves a ciphertext string.\n */\nimport { DomainKit, Principal, Reason, Storage } from \"domainkit\";\nimport { DateTime, Effect, Option, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport * as SqlError from \"effect/unstable/sql/SqlError\";\n\nimport type { Tables } from \"./tables.ts\";\n\ntype Fail = DomainKit.Error;\n\n// ---------------------------------------------------------------------------------------------\n// Errors\n// ---------------------------------------------------------------------------------------------\n\nconst fail = (reason: Reason.Model) => Effect.fail(new DomainKit.Error({ reason }));\n\nconst notFound = (entity: Reason.NotFound[\"entity\"], id: string) =>\n fail(new Reason.NotFound({ entity, id }));\n\nconst invalid = (message: string, field?: string) =>\n fail(new Reason.InvalidInput({ message, ...(field === undefined ? {} : { field }) }));\n\nconst busy = (key: string) => fail(new Reason.Busy({ key }));\n\nconst storageFailed = (operation: string, message: string) =>\n new DomainKit.Error({\n reason: new Reason.StorageFailed({ operation, message }),\n });\n\nconst sqlMessage = (error: SqlError.SqlError): string =>\n error.reason.cause instanceof Error\n ? `${error.reason._tag}: ${error.reason.cause.message}`\n : `${error.reason._tag}: ${String(error.reason.cause)}`;\n\n/**\n * Collapse the SQL error channel into `DomainKit.Error`.\n *\n * A `DomainKit.Error` raised by the body is the deliberate outcome of an invariant and passes\n * through unchanged; anything else is a driver failure and becomes `StorageFailed`.\n */\nconst guard =\n (operation: string) =>\n <A, R>(effect: Effect.Effect<A, SqlError.SqlError | Fail, R>): Effect.Effect<A, Fail, R> =>\n Effect.catch(effect, (error) =>\n Effect.fail(DomainKit.isError(error) ? error : storageFailed(operation, sqlMessage(error))),\n );\n\n// ---------------------------------------------------------------------------------------------\n// Row codecs\n// ---------------------------------------------------------------------------------------------\n\n/**\n * A row is stored as its schema's encoded form spread over columns, so the core schema stays the\n * only description of a row's shape. Reading reassembles the encoded object and decodes it.\n */\nconst codec = <S extends Schema.ConstraintCodec<unknown, unknown>>(schema: S, subject: string) => {\n const decode = Schema.decodeUnknownEffect(schema);\n const encode = Schema.encodeUnknownEffect(schema);\n return {\n read: (input: unknown): Effect.Effect<S[\"Type\"], Fail, S[\"DecodingServices\"]> =>\n decode(input).pipe(\n Effect.mapError((error) =>\n storageFailed(`${subject}.decode`, `stored ${subject} is invalid: ${error.message}`),\n ),\n ),\n write: (value: S[\"Type\"]): Effect.Effect<S[\"Encoded\"], Fail, S[\"EncodingServices\"]> =>\n encode(value).pipe(\n Effect.mapError((error) =>\n storageFailed(`${subject}.encode`, `${subject} cannot be stored: ${error.message}`),\n ),\n ),\n };\n};\n\nconst authorizationCodec = codec(Storage.Authorization, \"authorization\");\nconst connectionCodec = codec(Storage.Connection, \"connection\");\nconst attachmentCodec = codec(Storage.Attachment, \"attachment\");\nconst continuationCodec = codec(Storage.Continuation, \"continuation\");\nconst attemptCodec = codec(Storage.Attempt, \"attempt\");\nconst readinessCodec = codec(Storage.Readiness, \"readiness\");\nconst credentialCodec = codec(Storage.Credential, \"credential\");\n\n// ---------------------------------------------------------------------------------------------\n// Column conversions\n// ---------------------------------------------------------------------------------------------\n\n/** A `TIMESTAMPTZ` column as the ISO string every DomainKit timestamp schema encodes to. */\nconst iso = (value: unknown): string =>\n value instanceof Date ? value.toISOString() : String(value);\n\nconst isoOrNull = (value: unknown): string | null => (value === null ? null : iso(value));\n\n/** An ISO string from a schema's encoded form as the `Date` the driver binds to `TIMESTAMPTZ`. */\nconst at = (value: string): Date => new Date(value);\n\nconst atOrNull = (value: string | null): Date | null => (value === null ? null : at(value));\n\nconst now = Effect.map(DateTime.now, DateTime.toDateUtc);\n\n/**\n * A `JSONB` column as a plain value.\n *\n * Drivers disagree about whether they parse JSON columns, so accept both and normalize here\n * rather than depending on a host's client configuration.\n */\nconst fromJson = (value: unknown): unknown =>\n typeof value === \"string\" ? (JSON.parse(value) as unknown) : value;\n\nconst fromJsonOrNull = (value: unknown): unknown => (value === null ? null : fromJson(value));\n\n/** Bind a value to a `JSONB` column as text; PostgreSQL coerces the untyped parameter. */\nconst toJson = (value: unknown): string => JSON.stringify(value ?? null);\n\nconst toJsonOrNull = (value: unknown): string | null =>\n value === null || value === undefined ? null : toJson(value);\n\n// ---------------------------------------------------------------------------------------------\n// Row shapes\n// ---------------------------------------------------------------------------------------------\n\ninterface AuthorizationRow {\n readonly id: string;\n readonly owner_id: string;\n readonly provider: string;\n readonly method: string;\n readonly capabilities: unknown;\n readonly context: unknown;\n readonly revocation: string;\n readonly created_by: string;\n readonly created_at: unknown;\n readonly credential_ciphertext: string;\n readonly credential_expires_at: unknown;\n readonly credential_rotated_at: unknown;\n}\n\ninterface ConnectionRow {\n readonly id: string;\n readonly owner_id: string;\n readonly authorization_id: string;\n readonly created_at: unknown;\n}\n\ninterface AttachmentRow {\n readonly id: string;\n readonly owner_id: string;\n readonly connection_id: string;\n readonly domain: string;\n readonly zone: string;\n readonly target: unknown;\n readonly created_at: unknown;\n}\n\ninterface ContinuationRow {\n readonly id: string;\n readonly owner_id: string;\n readonly actor_id: string;\n readonly provider: string;\n readonly payload: unknown;\n readonly return_to: string | null;\n readonly expires_at: unknown;\n}\n\ninterface AttemptRow {\n readonly id: string;\n readonly owner_id: string;\n readonly attachment_id: string;\n readonly kind: string;\n readonly status: string;\n readonly plan: unknown;\n readonly approval: unknown;\n readonly receipt: unknown;\n readonly rejection: unknown;\n readonly source_receipt_id: string | null;\n readonly lease_expires_at: unknown;\n readonly failure: string | null;\n readonly updated_at: unknown;\n}\n\ninterface ReadinessRow {\n readonly owner_id: string;\n readonly domain: string;\n readonly attachment_id: string | null;\n readonly overall: string;\n readonly requirements: unknown;\n readonly host: unknown;\n readonly pending_since: unknown;\n readonly checked_at: unknown;\n readonly next_check_at: unknown;\n}\n\nconst authorizationOf = (row: AuthorizationRow) =>\n authorizationCodec.read({\n id: row.id,\n ownerId: row.owner_id,\n provider: row.provider,\n method: row.method,\n capabilities: fromJson(row.capabilities),\n context: fromJson(row.context),\n revocation: row.revocation,\n createdBy: row.created_by,\n createdAt: iso(row.created_at),\n });\n\nconst credentialOf = (row: AuthorizationRow) =>\n credentialCodec.read({\n ciphertext: row.credential_ciphertext,\n expiresAt: isoOrNull(row.credential_expires_at),\n rotatedAt: iso(row.credential_rotated_at),\n });\n\nconst connectionOf = (row: ConnectionRow) =>\n connectionCodec.read({\n id: row.id,\n ownerId: row.owner_id,\n authorizationId: row.authorization_id,\n createdAt: iso(row.created_at),\n });\n\nconst attachmentOf = (row: AttachmentRow) =>\n attachmentCodec.read({\n id: row.id,\n ownerId: row.owner_id,\n connectionId: row.connection_id,\n domain: row.domain,\n zone: row.zone,\n target: fromJson(row.target),\n createdAt: iso(row.created_at),\n });\n\nconst continuationOf = (row: ContinuationRow) =>\n continuationCodec.read({\n id: row.id,\n ownerId: row.owner_id,\n actorId: row.actor_id,\n provider: row.provider,\n payload: fromJson(row.payload),\n returnTo: row.return_to,\n expiresAt: iso(row.expires_at),\n });\n\nconst attemptOf = (row: AttemptRow) =>\n attemptCodec.read({\n id: row.id,\n ownerId: row.owner_id,\n attachmentId: row.attachment_id,\n kind: row.kind,\n status: row.status,\n plan: fromJson(row.plan),\n approval: fromJsonOrNull(row.approval),\n receipt: fromJsonOrNull(row.receipt),\n rejection: fromJsonOrNull(row.rejection),\n sourceReceiptId: row.source_receipt_id,\n leaseExpiresAt: isoOrNull(row.lease_expires_at),\n failure: row.failure,\n updatedAt: iso(row.updated_at),\n });\n\nconst readinessOf = (row: ReadinessRow) =>\n readinessCodec.read({\n domain: row.domain,\n attachmentId: row.attachment_id,\n ownerId: row.owner_id,\n overall: row.overall,\n requirements: fromJson(row.requirements),\n host: fromJson(row.host),\n pendingSince: isoOrNull(row.pending_since),\n checkedAt: iso(row.checked_at),\n nextCheckAt: isoOrNull(row.next_check_at),\n });\n\nconst stale = (attempt: Storage.Attempt) =>\n fail(new Reason.Stale({ planId: attempt.id, digest: attempt.plan.digest }));\n\n/** `prefix_<uuid>`, the same identifier shape the memory implementation mints. */\nconst fresh = (prefix: string) => Effect.sync(() => `${prefix}_${crypto.randomUUID()}`);\n\n// ---------------------------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------------------------\n\nexport const make = (\n tables: Tables,\n): Effect.Effect<Storage.Interface, never, SqlClient.SqlClient> =>\n Effect.gen(function* () {\n const client = yield* SqlClient.SqlClient;\n // A host may configure result-name transforms for its own tables; these queries read the exact\n // snake_case columns the capsule declared.\n const sql = client.withoutTransforms();\n\n const authorizations = sql(tables.authorizations.name);\n const connections = sql(tables.connections.name);\n const attachments = sql(tables.attachments.name);\n const continuations = sql(tables.continuations.name);\n const attempts = sql(tables.attempts.name);\n const readiness = sql(tables.readiness.name);\n\n /** The row this principal owns, locked for the rest of the transaction. */\n const lockedAuthorization = (owner: string, id: string) =>\n sql<AuthorizationRow>`\n SELECT * FROM ${authorizations} WHERE id = ${id} AND owner_id = ${owner} FOR UPDATE\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"authorization\", id) : Effect.succeed(rows[0]),\n ),\n );\n\n const lockedAttempt = (owner: string, id: string) =>\n sql<AttemptRow>`\n SELECT * FROM ${attempts} WHERE id = ${id} AND owner_id = ${owner} FOR UPDATE\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"plan\", id) : Effect.succeed(rows[0]),\n ),\n Effect.flatMap(attemptOf),\n );\n\n const requireConnection = (owner: string, id: string) =>\n sql<ConnectionRow>`\n SELECT * FROM ${connections} WHERE id = ${id} AND owner_id = ${owner}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"connection\", id) : Effect.succeed(rows[0]),\n ),\n );\n\n const requireAttachment = (owner: string, id: string) =>\n sql<AttachmentRow>`\n SELECT * FROM ${attachments} WHERE id = ${id} AND owner_id = ${owner}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"attachment\", id) : Effect.succeed(rows[0]),\n ),\n );\n\n const writeAuthorization = (\n authorization: Storage.Authorization,\n credential: Storage.Credential,\n ) =>\n Effect.all({\n row: authorizationCodec.write(authorization),\n secret: credentialCodec.write(credential),\n });\n\n /**\n * Phase one of revocation: mark the row `pending` so a crash between the provider call and the\n * delete is recoverable. Idempotent, and it never widens the row's state.\n *\n * Returns the ciphertext the caller is about to have revoked, which phase two checks.\n */\n const prepareRevocation = (owner: string, id: string) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const row = yield* lockedAuthorization(owner, id);\n yield* sql`\n UPDATE ${authorizations} SET revocation = 'pending', updated_at = ${yield* now}\n WHERE id = ${id} AND owner_id = ${owner}\n `;\n return row.credential_ciphertext;\n }),\n );\n\n /**\n * Phase two: delete the row, but only while it still holds the credential the provider was\n * asked to revoke.\n *\n * A credential refresh runs concurrently with revocation and rotates the row after the provider\n * call selected the old ciphertext. Deleting unconditionally would drop the row while the newly\n * issued credential is still live at the provider, with no local state left to revoke it from.\n * Leaving the row `pending` instead hands it to `recoverRevocations`, which revokes what the\n * row now holds. Every ciphertext is AES-GCM with a fresh IV, so equality here is exact.\n */\n const completeRevocation = (owner: string, id: string, ciphertext: string) =>\n sql`\n DELETE FROM ${authorizations}\n WHERE id = ${id} AND owner_id = ${owner} AND credential_ciphertext = ${ciphertext}\n `;\n\n const service: Storage.Interface = {\n authorizations: {\n upsert: ({ authorization, credential, expectedId }) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n if (authorization.ownerId !== ownerId) {\n return yield* invalid(\n \"Authorization owner does not match the principal\",\n \"ownerId\",\n );\n }\n const { row, secret } = yield* writeAuthorization(authorization, credential);\n const stamp = yield* now;\n return yield* sql.withTransaction(\n Effect.gen(function* () {\n if (expectedId !== undefined) {\n const current = yield* lockedAuthorization(ownerId, expectedId);\n if (current.revocation !== \"active\") {\n return yield* busy(`authorization:${expectedId}`);\n }\n if (authorization.id !== expectedId) {\n return yield* invalid(\"Authorization id must match expectedId\", \"id\");\n }\n // A replace overwrites every column the caller supplied, including `created_at`:\n // the row it returns has to be the row a later `get` reads back.\n yield* sql`\n UPDATE ${authorizations} SET\n provider = ${row.provider},\n method = ${row.method},\n capabilities = ${toJson(row.capabilities)},\n context = ${toJson(row.context)},\n revocation = ${row.revocation},\n created_by = ${row.createdBy},\n created_at = ${at(row.createdAt)},\n credential_ciphertext = ${secret.ciphertext},\n credential_expires_at = ${atOrNull(secret.expiresAt)},\n credential_rotated_at = ${at(secret.rotatedAt)},\n updated_at = ${stamp}\n WHERE id = ${expectedId} AND owner_id = ${ownerId}\n `;\n return authorization;\n }\n // An id already taken by any tenant is a caller defect, not a missing row, so the\n // insert claims it atomically instead of racing a prior existence check.\n const inserted = yield* sql<{ readonly id: string }>`\n INSERT INTO ${authorizations} (\n id, owner_id, provider, method, capabilities, context, revocation,\n created_by, created_at, credential_ciphertext, credential_expires_at,\n credential_rotated_at, updated_at\n ) VALUES (\n ${row.id}, ${row.ownerId}, ${row.provider}, ${row.method},\n ${toJson(row.capabilities)}, ${toJson(row.context)}, ${row.revocation},\n ${row.createdBy}, ${at(row.createdAt)}, ${secret.ciphertext},\n ${atOrNull(secret.expiresAt)}, ${at(secret.rotatedAt)}, ${stamp}\n ) ON CONFLICT (id) DO NOTHING RETURNING id\n `;\n return inserted[0] === undefined\n ? yield* invalid(`Authorization ${authorization.id} already exists`, \"id\")\n : authorization;\n }),\n );\n }),\n ).pipe(guard(\"authorizations.upsert\")),\n get: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AuthorizationRow>`\n SELECT * FROM ${authorizations} WHERE id = ${id} AND owner_id = ${ownerId}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"authorization\", id) : authorizationOf(rows[0]),\n ),\n ),\n ).pipe(guard(\"authorizations.get\")),\n credential: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AuthorizationRow>`\n SELECT * FROM ${authorizations} WHERE id = ${id} AND owner_id = ${ownerId}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"authorization\", id) : credentialOf(rows[0]),\n ),\n ),\n ).pipe(guard(\"authorizations.credential\")),\n rotate: (id, credential) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n const secret = yield* credentialCodec.write(credential);\n const updated = yield* sql<{ readonly id: string }>`\n UPDATE ${authorizations} SET\n credential_ciphertext = ${secret.ciphertext},\n credential_expires_at = ${atOrNull(secret.expiresAt)},\n credential_rotated_at = ${at(secret.rotatedAt)},\n updated_at = ${yield* now}\n WHERE id = ${id} AND owner_id = ${ownerId} RETURNING id\n `;\n if (updated[0] === undefined) return yield* notFound(\"authorization\", id);\n }),\n ).pipe(guard(\"authorizations.rotate\")),\n promoteCapabilities: (id, capabilities) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const current = yield* authorizationOf(yield* lockedAuthorization(ownerId, id));\n const merged = [...new Set([...current.capabilities, ...capabilities])];\n yield* sql`\n UPDATE ${authorizations}\n SET capabilities = ${toJson(merged)}, updated_at = ${yield* now}\n WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n }),\n ),\n ).pipe(guard(\"authorizations.promoteCapabilities\")),\n revoke: (id, revoke) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n const ciphertext = yield* prepareRevocation(ownerId, id).pipe(\n guard(\"authorizations.revoke\"),\n );\n yield* revoke;\n yield* completeRevocation(ownerId, id, ciphertext).pipe(\n guard(\"authorizations.completeRevocation\"),\n );\n }),\n ),\n recoverRevocations: (revoke) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n const rows = yield* sql<AuthorizationRow>`\n SELECT * FROM ${authorizations}\n WHERE owner_id = ${ownerId} AND revocation = 'pending'\n ORDER BY created_at\n `.pipe(guard(\"authorizations.pendingRevocations\"));\n yield* Effect.forEach(rows, (row) =>\n Effect.gen(function* () {\n yield* revoke(yield* authorizationOf(row));\n yield* completeRevocation(ownerId, row.id, row.credential_ciphertext).pipe(\n guard(\"authorizations.completeRevocation\"),\n );\n }),\n );\n return rows.length;\n }),\n ),\n },\n connections: {\n create: (authorizationId) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n yield* lockedAuthorization(ownerId, authorizationId);\n const row = new Storage.Connection({\n id: yield* fresh(\"conn\"),\n ownerId,\n authorizationId,\n createdAt: yield* DateTime.now,\n });\n const encoded = yield* connectionCodec.write(row);\n yield* sql`\n INSERT INTO ${connections} (id, owner_id, authorization_id, created_at)\n VALUES (${encoded.id}, ${encoded.ownerId}, ${encoded.authorizationId},\n ${at(encoded.createdAt)})\n `;\n return row;\n }),\n ),\n ).pipe(guard(\"connections.create\")),\n get: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.flatMap(requireConnection(ownerId, id), connectionOf),\n ).pipe(guard(\"connections.get\")),\n list: (filter) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.flatMap(\n filter?.provider === undefined\n ? sql<ConnectionRow>`\n SELECT * FROM ${connections} WHERE owner_id = ${ownerId} ORDER BY created_at\n `\n : sql<ConnectionRow>`\n SELECT c.* FROM ${connections} AS c\n JOIN ${authorizations} AS a ON a.id = c.authorization_id\n WHERE c.owner_id = ${ownerId} AND a.provider = ${filter.provider}\n ORDER BY c.created_at\n `,\n (rows) => Effect.forEach(rows, connectionOf),\n ),\n ).pipe(guard(\"connections.list\")),\n remove: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const rows = yield* sql<ConnectionRow>`\n SELECT * FROM ${connections}\n WHERE id = ${id} AND owner_id = ${ownerId} FOR UPDATE\n `;\n if (rows[0] === undefined) return yield* notFound(\"connection\", id);\n const held = yield* sql<{ readonly id: string }>`\n SELECT id FROM ${attachments}\n WHERE connection_id = ${id} AND owner_id = ${ownerId} LIMIT 1\n `;\n if (held[0] !== undefined) {\n return yield* invalid(`Connection ${id} still has attachments`, \"connectionId\");\n }\n yield* sql`DELETE FROM ${connections} WHERE id = ${id} AND owner_id = ${ownerId}`;\n }),\n ),\n ).pipe(guard(\"connections.remove\")),\n },\n attachments: {\n create: (input) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n yield* requireConnection(ownerId, input.connectionId);\n const row = new Storage.Attachment({\n id: yield* fresh(\"att\"),\n ownerId,\n connectionId: input.connectionId,\n domain: input.domain,\n zone: input.zone,\n target: input.target,\n createdAt: yield* DateTime.now,\n });\n const encoded = yield* attachmentCodec.write(row);\n // The unique (owner_id, domain) constraint decides the duplicate, so two concurrent\n // attaches cannot both win.\n const inserted = yield* sql<{ readonly id: string }>`\n INSERT INTO ${attachments} (\n id, owner_id, connection_id, domain, zone, target, created_at\n ) VALUES (\n ${encoded.id}, ${encoded.ownerId}, ${encoded.connectionId}, ${encoded.domain},\n ${encoded.zone}, ${toJson(encoded.target)}, ${at(encoded.createdAt)}\n ) ON CONFLICT (owner_id, domain) DO NOTHING RETURNING id\n `;\n return inserted[0] === undefined\n ? yield* invalid(`${input.domain} is already attached`, \"domain\")\n : row;\n }),\n ),\n ).pipe(guard(\"attachments.create\")),\n get: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.flatMap(requireAttachment(ownerId, id), attachmentOf),\n ).pipe(guard(\"attachments.get\")),\n byDomain: (domain) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AttachmentRow>`\n SELECT * FROM ${attachments} WHERE owner_id = ${ownerId} AND domain = ${domain}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined\n ? Effect.succeedNone\n : Effect.map(attachmentOf(rows[0]), Option.some),\n ),\n ),\n ).pipe(guard(\"attachments.byDomain\")),\n list: (connectionId) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n yield* requireConnection(ownerId, connectionId);\n const rows = yield* sql<AttachmentRow>`\n SELECT * FROM ${attachments}\n WHERE owner_id = ${ownerId} AND connection_id = ${connectionId}\n ORDER BY created_at\n `;\n return yield* Effect.forEach(rows, attachmentOf);\n }),\n ).pipe(guard(\"attachments.list\")),\n remove: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n yield* requireAttachment(ownerId, id);\n // Readiness is keyed by domain and outlives the attachment, so clear the link\n // rather than the row: what was observed about the domain is still true, and a\n // dangling attachment id would fail the next `readiness.put`.\n yield* sql`\n UPDATE ${readiness} SET attachment_id = NULL\n WHERE attachment_id = ${id} AND owner_id = ${ownerId}\n `;\n yield* sql`DELETE FROM ${attachments} WHERE id = ${id} AND owner_id = ${ownerId}`;\n }),\n ),\n ).pipe(guard(\"attachments.remove\")),\n },\n continuations: {\n put: (continuation) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n if (continuation.ownerId !== ownerId) {\n return yield* invalid(\"Continuation owner does not match the principal\", \"ownerId\");\n }\n const encoded = yield* continuationCodec.write(continuation);\n yield* sql`\n INSERT INTO ${continuations} (\n id, owner_id, actor_id, provider, payload, return_to, expires_at\n ) VALUES (\n ${encoded.id}, ${encoded.ownerId}, ${encoded.actorId}, ${encoded.provider},\n ${toJson(encoded.payload)}, ${encoded.returnTo}, ${at(encoded.expiresAt)}\n ) ON CONFLICT (id) DO UPDATE SET\n owner_id = EXCLUDED.owner_id,\n actor_id = EXCLUDED.actor_id,\n provider = EXCLUDED.provider,\n payload = EXCLUDED.payload,\n return_to = EXCLUDED.return_to,\n expires_at = EXCLUDED.expires_at\n `;\n }),\n ).pipe(guard(\"continuations.put\")),\n get: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n // A read, not a claim: the row survives so `consume` can still spend it.\n const rows = yield* sql<ContinuationRow>`\n SELECT * FROM ${continuations} WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n if (rows[0] === undefined) return yield* notFound(\"continuation\", id);\n const continuation = yield* continuationOf(rows[0]);\n const instant = yield* DateTime.now;\n return DateTime.toEpochMillis(continuation.expiresAt) <=\n DateTime.toEpochMillis(instant)\n ? yield* fail(new Reason.Expired({ entity: \"continuation\", id }))\n : continuation;\n }),\n ).pipe(guard(\"continuations.get\")),\n consume: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n // The delete is the claim: a second consume finds nothing, expired or not.\n const rows = yield* sql<ContinuationRow>`\n DELETE FROM ${continuations}\n WHERE id = ${id} AND owner_id = ${ownerId} RETURNING *\n `;\n if (rows[0] === undefined) return yield* notFound(\"continuation\", id);\n const continuation = yield* continuationOf(rows[0]);\n const instant = yield* DateTime.now;\n return DateTime.toEpochMillis(continuation.expiresAt) <=\n DateTime.toEpochMillis(instant)\n ? yield* fail(new Reason.Expired({ entity: \"continuation\", id }))\n : continuation;\n }),\n ).pipe(guard(\"continuations.consume\")),\n },\n attempts: {\n create: (attempt) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n if (attempt.ownerId !== ownerId) {\n return yield* invalid(\"Attempt owner does not match the principal\", \"ownerId\");\n }\n const encoded = yield* attemptCodec.write(attempt);\n const inserted = yield* sql<{ readonly id: string }>`\n INSERT INTO ${attempts} (\n id, owner_id, attachment_id, kind, status, plan, approval, approval_id,\n receipt, receipt_id, rejection, source_receipt_id, lease_expires_at, failure,\n plan_created_at, updated_at\n ) VALUES (\n ${encoded.id}, ${encoded.ownerId}, ${encoded.attachmentId}, ${encoded.kind},\n ${encoded.status}, ${toJson(encoded.plan)}, ${toJsonOrNull(encoded.approval)},\n ${attempt.approval?.id ?? null}, ${toJsonOrNull(encoded.receipt)},\n ${attempt.receipt?.id ?? null}, ${toJsonOrNull(encoded.rejection)},\n ${encoded.sourceReceiptId},\n ${atOrNull(encoded.leaseExpiresAt)}, ${encoded.failure},\n ${at(encoded.plan.createdAt)}, ${at(encoded.updatedAt)}\n ) ON CONFLICT (id) DO NOTHING RETURNING id\n `;\n return inserted[0] === undefined\n ? yield* invalid(`Plan ${attempt.id} already exists`, \"id\")\n : attempt;\n }),\n ).pipe(guard(\"attempts.create\")),\n get: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AttemptRow>`\n SELECT * FROM ${attempts} WHERE id = ${id} AND owner_id = ${ownerId}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"plan\", id) : attemptOf(rows[0]),\n ),\n ),\n ).pipe(guard(\"attempts.get\")),\n byApproval: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AttemptRow>`\n SELECT * FROM ${attempts} WHERE approval_id = ${id} AND owner_id = ${ownerId}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"approval\", id) : attemptOf(rows[0]),\n ),\n ),\n ).pipe(guard(\"attempts.byApproval\")),\n byReceipt: (id) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AttemptRow>`\n SELECT * FROM ${attempts} WHERE receipt_id = ${id} AND owner_id = ${ownerId}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined ? notFound(\"receipt\", id) : attemptOf(rows[0]),\n ),\n ),\n ).pipe(guard(\"attempts.byReceipt\")),\n latest: (attachmentId, kind) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<AttemptRow>`\n SELECT * FROM ${attempts}\n WHERE owner_id = ${ownerId} AND attachment_id = ${attachmentId} AND kind = ${kind}\n ORDER BY plan_created_at DESC, updated_at DESC LIMIT 1\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined\n ? Effect.succeedNone\n : Effect.map(attemptOf(rows[0]), Option.some),\n ),\n ),\n ).pipe(guard(\"attempts.latest\")),\n approve: (id, approval) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const current = yield* lockedAttempt(ownerId, id);\n // Replaying the same approval is how a retried request stays safe.\n if (current.approval?.id === approval.id) return current;\n if (current.status !== \"planned\") return yield* stale(current);\n const next = new Storage.Attempt({\n ...current,\n status: \"approved\",\n approval,\n updatedAt: yield* DateTime.now,\n });\n const encoded = yield* attemptCodec.write(next);\n yield* sql`\n UPDATE ${attempts} SET\n status = ${encoded.status},\n approval = ${toJsonOrNull(encoded.approval)},\n approval_id = ${approval.id},\n updated_at = ${at(encoded.updatedAt)}\n WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n return next;\n }),\n ),\n ).pipe(guard(\"attempts.approve\")),\n reject: (id, input) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const current = yield* lockedAttempt(ownerId, id);\n // Terminal: a second rejection is the same outcome, so it returns the first one.\n if (current.status === \"rejected\") return current;\n if (current.status === \"expired\") {\n return yield* fail(new Reason.Expired({ entity: \"plan\", id }));\n }\n // A digest mismatch means the reviewer declined a plan that is no longer current.\n if (current.status !== \"planned\" || current.plan.digest !== input.digest) {\n return yield* stale(current);\n }\n const instant = yield* DateTime.now;\n const next = new Storage.Attempt({\n ...current,\n status: \"rejected\",\n rejection: { actorId: input.actorId, reason: input.reason, at: instant },\n updatedAt: instant,\n });\n const encoded = yield* attemptCodec.write(next);\n yield* sql`\n UPDATE ${attempts} SET\n status = ${encoded.status},\n rejection = ${toJsonOrNull(encoded.rejection)},\n updated_at = ${at(encoded.updatedAt)}\n WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n return next;\n }),\n ),\n ).pipe(guard(\"attempts.reject\")),\n claim: (id, lease) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const current = yield* lockedAttempt(ownerId, id);\n const instant = yield* DateTime.now;\n if (current.status === \"applying\") {\n const held =\n current.leaseExpiresAt !== null &&\n DateTime.toEpochMillis(current.leaseExpiresAt) >\n DateTime.toEpochMillis(instant);\n if (held) return yield* busy(`apply:${id}`);\n } else if (current.status !== \"approved\" && current.status !== \"failed\") {\n return yield* stale(current);\n }\n const next = new Storage.Attempt({\n ...current,\n status: \"applying\",\n leaseExpiresAt: lease,\n failure: null,\n updatedAt: instant,\n });\n const encoded = yield* attemptCodec.write(next);\n yield* sql`\n UPDATE ${attempts} SET\n status = ${encoded.status},\n lease_expires_at = ${atOrNull(encoded.leaseExpiresAt)},\n failure = NULL,\n updated_at = ${at(encoded.updatedAt)}\n WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n return next;\n }),\n ),\n ).pipe(guard(\"attempts.claim\")),\n complete: (id, receipt) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const current = yield* lockedAttempt(ownerId, id);\n if (current.status !== \"applying\") return yield* stale(current);\n const next = new Storage.Attempt({\n ...current,\n status: receipt.status,\n receipt,\n leaseExpiresAt: null,\n updatedAt: yield* DateTime.now,\n });\n const encoded = yield* attemptCodec.write(next);\n yield* sql`\n UPDATE ${attempts} SET\n status = ${encoded.status},\n receipt = ${toJsonOrNull(encoded.receipt)},\n receipt_id = ${receipt.id},\n lease_expires_at = NULL,\n updated_at = ${at(encoded.updatedAt)}\n WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n return next;\n }),\n ),\n ).pipe(guard(\"attempts.complete\")),\n fail: (id, message) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql.withTransaction(\n Effect.gen(function* () {\n const current = yield* lockedAttempt(ownerId, id);\n if (current.status !== \"applying\") return yield* stale(current);\n const next = new Storage.Attempt({\n ...current,\n status: \"failed\",\n failure: message,\n leaseExpiresAt: null,\n updatedAt: yield* DateTime.now,\n });\n const encoded = yield* attemptCodec.write(next);\n yield* sql`\n UPDATE ${attempts} SET\n status = ${encoded.status},\n failure = ${message},\n lease_expires_at = NULL,\n updated_at = ${at(encoded.updatedAt)}\n WHERE id = ${id} AND owner_id = ${ownerId}\n `;\n return next;\n }),\n ),\n ).pipe(guard(\"attempts.fail\")),\n },\n readiness: {\n put: (row) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.gen(function* () {\n if (row.ownerId !== ownerId) {\n return yield* invalid(\"Readiness owner does not match the principal\", \"ownerId\");\n }\n // A linked attachment has to exist for this owner; observe-only readiness has none.\n if (row.attachmentId !== null) yield* requireAttachment(ownerId, row.attachmentId);\n const encoded = yield* readinessCodec.write(row);\n yield* sql`\n INSERT INTO ${readiness} (\n owner_id, domain, attachment_id, overall, requirements, host, pending_since,\n checked_at, next_check_at\n ) VALUES (\n ${encoded.ownerId}, ${encoded.domain}, ${encoded.attachmentId},\n ${encoded.overall}, ${toJson(encoded.requirements)}, ${toJson(encoded.host)},\n ${atOrNull(encoded.pendingSince)}, ${at(encoded.checkedAt)},\n ${atOrNull(encoded.nextCheckAt)}\n ) ON CONFLICT (owner_id, domain) DO UPDATE SET\n attachment_id = EXCLUDED.attachment_id,\n overall = EXCLUDED.overall,\n requirements = EXCLUDED.requirements,\n host = EXCLUDED.host,\n pending_since = EXCLUDED.pending_since,\n checked_at = EXCLUDED.checked_at,\n next_check_at = EXCLUDED.next_check_at\n `;\n }),\n ).pipe(guard(\"readiness.put\")),\n get: (domain) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n sql<ReadinessRow>`\n SELECT * FROM ${readiness}\n WHERE owner_id = ${ownerId} AND domain = ${domain}\n `.pipe(\n Effect.flatMap((rows) =>\n rows[0] === undefined\n ? Effect.succeedNone\n : Effect.map(readinessOf(rows[0]), Option.some),\n ),\n ),\n ).pipe(guard(\"readiness.get\")),\n },\n withLock: (key, effect) =>\n Effect.flatMap(Principal.Service, ({ ownerId }) =>\n Effect.scoped(\n Effect.gen(function* () {\n // A session lock, not a transaction lock: the guarded effect refreshes a credential\n // against the provider, and no transaction should stay open across an HTTP call.\n // `reserve` pins one pooled connection so the unlock runs on the session that took\n // the lock, and registering it after the connection makes it run first on release.\n const connection = yield* Effect.mapError(sql.reserve, (error) =>\n storageFailed(\"withLock\", sqlMessage(error)),\n );\n const scoped = `${ownerId}:${key}`;\n yield* Effect.acquireRelease(\n connection\n .execute(\n \"SELECT pg_try_advisory_lock(hashtextextended($1, 0)) AS acquired\",\n [scoped],\n undefined,\n )\n .pipe(\n Effect.mapError((error: SqlError.SqlError) =>\n storageFailed(\"withLock\", sqlMessage(error)),\n ),\n Effect.flatMap((rows: ReadonlyArray<{ readonly acquired: boolean }>) =>\n rows[0]?.acquired === true ? Effect.void : busy(key),\n ),\n ),\n () =>\n connection\n .execute(\n \"SELECT pg_advisory_unlock(hashtextextended($1, 0))\",\n [scoped],\n undefined,\n )\n .pipe(Effect.ignore),\n );\n return yield* effect;\n }),\n ),\n ),\n };\n\n return service;\n });\n","/**\n * The six tables DomainKit owns, declared once and rendered per dialect by CapsuleDB.\n *\n * Every table carries `owner_id` and every query filters by it: tenancy is a column, not a schema.\n * There are no foreign keys to host tables, and none between DomainKit's own tables either, so a\n * host can add its own in the emitted migration without fighting a constraint the package owns.\n */\nimport { Schema } from \"capsuledb\";\n\nexport interface Tables {\n readonly authorizations: Schema.Table;\n readonly connections: Schema.Table;\n readonly attachments: Schema.Table;\n readonly continuations: Schema.Table;\n readonly attempts: Schema.Table;\n readonly readiness: Schema.Table;\n}\n\n/** Default table prefix. Part of the physical layout, so it is immutable after the first deploy. */\nexport const DEFAULT_PREFIX = \"domainkit\";\n\n/**\n * Declare the six tables under `prefix`.\n *\n * `Schema.table` validates every identifier it will quote, so an invalid prefix throws\n * `CapsuleDefinitionError` here rather than reaching a renderer.\n */\nexport const make = (prefix: string): Tables => ({\n authorizations: Schema.table(`${prefix}_authorizations`, {\n columns: {\n id: Schema.text(),\n owner_id: Schema.text(),\n provider: Schema.text(),\n method: Schema.text(),\n capabilities: Schema.json(),\n context: Schema.json(),\n revocation: Schema.text(),\n created_by: Schema.text(),\n created_at: Schema.timestamp(),\n credential_ciphertext: Schema.text(),\n credential_expires_at: Schema.timestamp({ nullable: true }),\n credential_rotated_at: Schema.timestamp(),\n updated_at: Schema.timestamp(),\n },\n primaryKey: [\"id\"],\n indexes: [{ columns: [\"owner_id\", \"revocation\"] }, { columns: [\"owner_id\", \"provider\"] }],\n }),\n connections: Schema.table(`${prefix}_connections`, {\n columns: {\n id: Schema.text(),\n owner_id: Schema.text(),\n authorization_id: Schema.text(),\n created_at: Schema.timestamp(),\n },\n primaryKey: [\"id\"],\n indexes: [{ columns: [\"owner_id\"] }, { columns: [\"authorization_id\"] }],\n }),\n attachments: Schema.table(`${prefix}_attachments`, {\n columns: {\n id: Schema.text(),\n owner_id: Schema.text(),\n connection_id: Schema.text(),\n domain: Schema.text(),\n zone: Schema.text(),\n target: Schema.json(),\n created_at: Schema.timestamp(),\n },\n primaryKey: [\"id\"],\n // One attachment per domain per tenant; `attachments.create` reads the conflict as InvalidInput.\n uniques: [[\"owner_id\", \"domain\"]],\n indexes: [{ columns: [\"owner_id\", \"connection_id\"] }],\n }),\n continuations: Schema.table(`${prefix}_continuations`, {\n columns: {\n id: Schema.text(),\n owner_id: Schema.text(),\n actor_id: Schema.text(),\n provider: Schema.text(),\n payload: Schema.json(),\n return_to: Schema.text({ nullable: true }),\n expires_at: Schema.timestamp(),\n },\n primaryKey: [\"id\"],\n // Hosts sweep expired rows on this index; consume deletes the row it returns.\n indexes: [{ columns: [\"expires_at\"] }],\n }),\n attempts: Schema.table(`${prefix}_attempts`, {\n columns: {\n id: Schema.text(),\n owner_id: Schema.text(),\n attachment_id: Schema.text(),\n kind: Schema.text(),\n status: Schema.text(),\n plan: Schema.json(),\n approval: Schema.json({ nullable: true }),\n /** Denormalized from `approval` so `byApproval` is an index lookup. */\n approval_id: Schema.text({ nullable: true }),\n receipt: Schema.json({ nullable: true }),\n /** Denormalized from `receipt` so `byReceipt` is an index lookup. */\n receipt_id: Schema.text({ nullable: true }),\n /** Who declined the plan, why, and when; set when an attempt reaches `rejected`. */\n rejection: Schema.json({ nullable: true }),\n source_receipt_id: Schema.text({ nullable: true }),\n lease_expires_at: Schema.timestamp({ nullable: true }),\n failure: Schema.text({ nullable: true }),\n /** The plan's own `createdAt`; `latest` orders by it. */\n plan_created_at: Schema.timestamp(),\n updated_at: Schema.timestamp(),\n },\n primaryKey: [\"id\"],\n indexes: [\n { columns: [\"owner_id\", \"attachment_id\", \"kind\"] },\n { columns: [\"owner_id\", \"approval_id\"] },\n { columns: [\"owner_id\", \"receipt_id\"] },\n ],\n }),\n readiness: Schema.table(`${prefix}_readiness`, {\n columns: {\n owner_id: Schema.text(),\n domain: Schema.text(),\n /** Set while an attachment covers the domain; observe-only readiness leaves it null. */\n attachment_id: Schema.text({ nullable: true }),\n overall: Schema.text(),\n requirements: Schema.json(),\n host: Schema.json(),\n pending_since: Schema.timestamp({ nullable: true }),\n checked_at: Schema.timestamp(),\n next_check_at: Schema.timestamp({ nullable: true }),\n },\n // Keyed by domain, not by attachment, so a host observing public DNS alone gets the same row.\n primaryKey: [\"owner_id\", \"domain\"],\n // The sweep index drives the backoff ladder; the attachment index is for clearing the link.\n indexes: [{ columns: [\"owner_id\", \"next_check_at\"] }, { columns: [\"attachment_id\"] }],\n }),\n});\n\nexport const list = (tables: Tables): ReadonlyArray<Schema.Table> => [\n tables.authorizations,\n tables.connections,\n tables.attachments,\n tables.continuations,\n tables.attempts,\n tables.readiness,\n];\n","/**\n * DomainKit's CapsuleDB capsule: six tables and one `Storage.Service` implementation.\n *\n * The capsule is a plain value, so a host imports it, points `capsuledb emit` at it, or hands it\n * to `Registry.layer` without running an Effect first.\n */\nimport { Capsule, Migration } from \"capsuledb\";\nimport { Storage } from \"domainkit\";\nimport { Layer } from \"effect\";\nimport type * as SqlClient from \"effect/unstable/sql/SqlClient\";\n\nimport { make as makeService } from \"./internal/storage.ts\";\nimport { DEFAULT_PREFIX, list, make as makeTables } from \"./internal/tables.ts\";\n\nexport { DEFAULT_PREFIX };\n\n/**\n * Build the capsule for a table prefix.\n *\n * The prefix is part of the physical layout: it changes the rendered DDL and therefore the\n * migration checksums, so a deployed registry must keep the prefix it was created with.\n */\nexport const make = (\n prefix: string = DEFAULT_PREFIX,\n): Capsule.Capsule<Storage.Service, never, SqlClient.SqlClient> => {\n const tables = makeTables(prefix);\n return Capsule.make({\n id: \"domainkit.storage\",\n tables: list(tables),\n migrations: [\n Migration.make({\n id: 1,\n name: \"create-storage\",\n risk: \"additive\",\n steps: list(tables).map(Migration.createTable),\n }),\n ],\n layer: Layer.effect(Storage.Service)(makeService(tables)),\n });\n};\n\n/** The capsule under the default `domainkit` prefix. `capsuledb emit --export capsule` reads this. */\nexport const capsule: Capsule.Capsule<Storage.Service, never, SqlClient.SqlClient> = make();\n","/**\n * The layer a host installs: DomainKit's `Storage` on the host's own PostgreSQL client.\n *\n * `layer()` runs the capsule through CapsuleDB's registry, which creates the ledger, applies\n * pending migrations, and only then provides `Storage`. A host that owns its migration pipeline\n * applies `capsuledb emit` output instead and boots with `mode: \"assert\"`, which touches no schema\n * and fails unless the database already matches the capsule.\n *\n * The layer requires only `SqlClient`: credentials arrive sealed, so Storage never needs `Custody`.\n */\nimport { Pg, type Registry as RegistryTypes, Registry } from \"capsuledb\";\nimport type { Storage } from \"domainkit\";\nimport type * as Layer from \"effect/Layer\";\nimport type * as SqlClient from \"effect/unstable/sql/SqlClient\";\n\nimport { capsule, DEFAULT_PREFIX, make } from \"./capsule.ts\";\n\nexport interface Options {\n /** Table prefix. Default `domainkit`. Part of the physical layout; immutable after first deploy. */\n readonly prefix?: string;\n /** `prepare` (default) migrates at boot; `assert` expects the host applied `capsuledb emit` output. */\n readonly mode?: \"prepare\" | \"assert\";\n /**\n * Prefix for CapsuleDB's own ledger tables; default `capsuledb`. Set it only to match a prefix a\n * host already uses for other capsules, and pass the same value to `capsuledb emit --prefix`.\n */\n readonly registryPrefix?: string;\n}\n\nexport const layer = (\n options: Options = {},\n): Layer.Layer<Storage.Service, RegistryTypes.RegistryRuntimeError, SqlClient.SqlClient> =>\n Registry.layer({\n provider: Pg.profile,\n capsules: [\n options.prefix === undefined || options.prefix === DEFAULT_PREFIX\n ? capsule\n : make(options.prefix),\n ],\n ...(options.mode === undefined ? {} : { mode: options.mode }),\n ...(options.registryPrefix === undefined ? {} : { prefix: options.registryPrefix }),\n });\n","/**\n * DomainKit's `Storage` on PostgreSQL, as one declarative CapsuleDB capsule.\n *\n * Hosts install `PgStorage.layer()` under `DomainKit.layer` and supply their own `SqlClient`. The\n * `capsule` value is the same declaration `capsuledb emit` reads to write SQL for a host-owned\n * migration pipeline.\n */\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const VERSION = packageJson.version;\n\nexport * as PgStorage from \"./PgStorage.ts\";\nexport { capsule } from \"./capsule.ts\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@domainkit/capsuledb",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "DomainKit Storage on PostgreSQL, as one declarative CapsuleDB capsule",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dns",
|
|
7
7
|
"domainkit",
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
"typecheck": "tsc --noEmit"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"domainkit": "^0.
|
|
48
|
+
"domainkit": "^0.9.0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@effect/sql-pg": "4.0.0-rc.112",
|
|
52
52
|
"@effect/vitest": "4.0.0-rc.112",
|
|
53
53
|
"@testcontainers/postgresql": "12.1.0",
|
|
54
54
|
"@types/bun": "1.4.0",
|
|
55
|
-
"capsuledb": "
|
|
55
|
+
"capsuledb": "0.2.0",
|
|
56
56
|
"drizzle-orm": "1.0.0-rc.5-ab785fc",
|
|
57
57
|
"effect": "4.0.0-rc.112",
|
|
58
58
|
"tsdown": "0.22.14",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"vitest": "4.1.11"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"capsuledb": ">=0.
|
|
63
|
+
"capsuledb": ">=0.2.0 <0.3.0",
|
|
64
64
|
"effect": ">=4.0.0-rc.112 <5.0.0"
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|