@opengeni/db 5.0.1 → 6.0.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/dist/automations.d.ts +0 -2
- package/dist/canonical-human-identities.d.ts +4 -0
- package/dist/canonical-human-identities.js +3 -3
- package/dist/capability-components.d.ts +5 -13
- package/dist/capability-integrations.d.ts +23 -8
- package/dist/capability-reconciliation.d.ts +5 -0
- package/dist/capability-reconciliation.js +21 -0
- package/dist/capability-reconciliation.js.map +1 -0
- package/dist/{chunk-6T2GGYWE.js → chunk-4UJCXBR2.js} +4 -5800
- package/dist/chunk-4UJCXBR2.js.map +1 -0
- package/dist/{chunk-MWMXWHJD.js → chunk-7JCDSMX2.js} +2 -2
- package/dist/chunk-AJA2ZIUW.js +219 -0
- package/dist/chunk-AJA2ZIUW.js.map +1 -0
- package/dist/chunk-CDAT6EKW.js +247 -0
- package/dist/chunk-CDAT6EKW.js.map +1 -0
- package/dist/{chunk-DPONPYJD.js → chunk-CJI6G254.js} +70 -18
- package/dist/chunk-CJI6G254.js.map +1 -0
- package/dist/chunk-G32NVMRJ.js +276 -0
- package/dist/chunk-G32NVMRJ.js.map +1 -0
- package/dist/chunk-GABXCG3N.js +5811 -0
- package/dist/chunk-GABXCG3N.js.map +1 -0
- package/dist/{chunk-ERKVSPDX.js → chunk-LVY33EWL.js} +3 -3
- package/dist/{chunk-45CP2YKY.js → chunk-MAMBI2HR.js} +9 -3
- package/dist/{chunk-45CP2YKY.js.map → chunk-MAMBI2HR.js.map} +1 -1
- package/dist/{chunk-F73UKJY6.js → chunk-MN5PZMEK.js} +91 -108
- package/dist/chunk-MN5PZMEK.js.map +1 -0
- package/dist/chunk-PJI4MUZ7.js +131 -0
- package/dist/chunk-PJI4MUZ7.js.map +1 -0
- package/dist/{chunk-T6BWIGWJ.js → chunk-RIYHP2WU.js} +2 -2
- package/dist/{chunk-7HMK3B45.js → chunk-RL2MUXM3.js} +16 -7
- package/dist/chunk-RL2MUXM3.js.map +1 -0
- package/dist/{chunk-HQDVI2DB.js → chunk-SYKHLPTK.js} +4 -3
- package/dist/{chunk-HQDVI2DB.js.map → chunk-SYKHLPTK.js.map} +1 -1
- package/dist/{chunk-T6YLHJLS.js → chunk-XIXVVBW2.js} +198 -51
- package/dist/chunk-XIXVVBW2.js.map +1 -0
- package/dist/chunk-ZPJ6V2VG.js +156 -0
- package/dist/chunk-ZPJ6V2VG.js.map +1 -0
- package/dist/codex-capacity-recovery.d.ts +12 -0
- package/dist/codex-failure-eligibility.d.ts +9 -0
- package/dist/company-profile-schema.d.ts +4 -2
- package/dist/connect-attempts.d.ts +15 -0
- package/dist/connect-attempts.js +25 -0
- package/dist/connect-attempts.js.map +1 -0
- package/dist/connection-authority.d.ts +7 -63
- package/dist/connection-refresh-lock.d.ts +4 -0
- package/dist/connection-token-resolver.d.ts +8 -43
- package/dist/database-timing.d.ts +10 -0
- package/dist/database.d.ts +4 -0
- package/dist/editable-artifact-durable-export.js +2 -2
- package/dist/editable-artifacts.d.ts +9 -0
- package/dist/editable-artifacts.js +7 -5
- package/dist/index.d.ts +447 -78
- package/dist/index.js +12705 -12872
- package/dist/index.js.map +1 -1
- package/dist/insights-usage-bundle.d.ts +3 -0
- package/dist/integration-bindings.d.ts +1 -1
- package/dist/integration-facets.d.ts +18 -1
- package/dist/knowledge-entries-schema.d.ts +2 -0
- package/dist/knowledge-entries.d.ts +1 -0
- package/dist/knowledge-indexing.d.ts +1 -0
- package/dist/live-session-attempt.d.ts +35 -137
- package/dist/managed-auth-session-sets.js +3 -3
- package/dist/mcp-account-bindings.d.ts +4 -0
- package/dist/mcp-oauth.d.ts +11 -0
- package/dist/mcp-operations.js +2 -2
- package/dist/migrate.js +1 -1
- package/dist/organization-integration-policy.d.ts +51 -0
- package/dist/organization-integration-policy.js +18 -0
- package/dist/organization-integration-policy.js.map +1 -0
- package/dist/organization-usage.d.ts +20 -0
- package/dist/plugin-packages.d.ts +9 -12
- package/dist/pr-review.d.ts +0 -11
- package/dist/preference-registry-schema.d.ts +17 -0
- package/dist/provision-roles.js +1 -1
- package/dist/retained-provider-commands.d.ts +124 -6
- package/dist/retained-provider-commands.js +29 -97
- package/dist/retained-provider-commands.js.map +1 -1
- package/dist/retired-session-create-metadata.d.ts +4 -0
- package/dist/runtime-posture.d.ts +7 -5
- package/dist/schema.d.ts +876 -656
- package/dist/schema.js +5 -7
- package/dist/session-admission-block.d.ts +32 -0
- package/dist/session-attempt-writers.d.ts +4 -0
- package/dist/session-background-commands.js +5 -4
- package/dist/session-command-output.js +8 -126
- package/dist/session-command-output.js.map +1 -1
- package/dist/session-control.d.ts +5 -1
- package/dist/session-event-slices.d.ts +10 -0
- package/dist/session-event-slices.js +8 -222
- package/dist/session-event-slices.js.map +1 -1
- package/dist/session-file-attachments.d.ts +28 -0
- package/dist/session-goal-reports.d.ts +43 -0
- package/dist/session-mcp-approval.d.ts +4 -0
- package/dist/session-mcp-credential-rotation.js +5 -4
- package/dist/session-mcp-credential-rotation.js.map +1 -1
- package/dist/session-message-search.d.ts +22 -0
- package/dist/session-queue-commands.d.ts +2 -6
- package/dist/session-retry.d.ts +36 -0
- package/dist/session-tenancy.js +3 -3
- package/dist/skill-source-release-impact.d.ts +18 -0
- package/dist/skill-source-release.d.ts +9 -0
- package/dist/skills.d.ts +7 -1
- package/dist/user-resource-authority.d.ts +0 -8
- package/dist/video-generation.js +3 -3
- package/dist/workspace-tool-defaults.js +5 -4
- package/dist/workspace-tool-defaults.js.map +1 -1
- package/drizzle/0468_knowledge_relationship_projection.sql +30 -0
- package/drizzle/0469_knowledge_source_discovery.sql +85 -0
- package/drizzle/0470_organization_integration_policy.sql +151 -0
- package/drizzle/0471_usage_events_account_recent_index.sql +4 -0
- package/drizzle/0472_usage_events_workspace_recent_index.sql +4 -0
- package/drizzle/0473_organization_usage_analytical_capability.sql +237 -0
- package/drizzle/0474_goal_report_requirements.sql +156 -0
- package/drizzle/0475_session_event_history_statistics.sql +15 -0
- package/drizzle/0476_session_event_history_policy_planning.sql +29 -0
- package/drizzle/0477_managed_sign_in_methods.sql +303 -0
- package/drizzle/0478_sender_owned_connections.sql +2772 -0
- package/drizzle/0479_connection_create_idempotency.sql +16 -0
- package/drizzle/0480_private_session_organization_key_administration.sql +154 -0
- package/drizzle/0481_personal_connection_visibility_cleanup.sql +45 -0
- package/drizzle/0482_remove_packs.sql +417 -0
- package/drizzle/0483_preclaim_admission_block.sql +85 -0
- package/drizzle/0484_insights_usage_projection.sql +211 -0
- package/drizzle/0485_inherited_mcp_approval_policies.sql +6 -0
- package/drizzle/0486_reasoning_configuration_message_forks.sql +35 -0
- package/drizzle/0487_skill_catalog_message_forks.sql +26 -0
- package/drizzle/0488_permanent_skill_removal.sql +207 -0
- package/drizzle/0489_modal_command_byte_offsets.sql +17 -0
- package/drizzle/0490_periodic_capture_attempt_cadence.sql +6 -0
- package/drizzle/0491_warm_capture_holder_reclamation.sql +57 -0
- package/drizzle/0492_codex_accepted_source_authority.sql +249 -0
- package/drizzle/0493_stopping_command_error_containment.sql +58 -0
- package/drizzle/0494_mcp_account_bindings.sql +334 -0
- package/drizzle/0495_consented_sandbox_recovery.sql +220 -0
- package/drizzle/0496_supervised_command_settlement.sql +386 -0
- package/drizzle/0497_modal_inventory_owner_read_capability.sql +112 -0
- package/drizzle/0498_enrollment_membership_fence.sql +87 -0
- package/drizzle/0499_session_attachment_access.sql +224 -0
- package/drizzle/0500_session_execution_epoch.sql +37 -0
- package/drizzle/0501_session_sharing_execution.sql +591 -0
- package/drizzle/0502_active_message_boundary_forks.sql +30 -0
- package/package.json +17 -5
- package/src/automations.ts +17 -73
- package/src/canonical-human-identities.ts +17 -5
- package/src/capability-components.ts +7 -24
- package/src/capability-integrations.ts +301 -21
- package/src/capability-reconciliation.ts +19 -0
- package/src/codex-capacity-recovery.ts +47 -0
- package/src/codex-failure-eligibility.ts +93 -0
- package/src/connect-attempts.ts +49 -18
- package/src/connection-authority.ts +12 -158
- package/src/connection-refresh-lock.ts +22 -0
- package/src/connection-token-resolver.ts +58 -530
- package/src/database-timing.ts +43 -0
- package/src/database.ts +61 -26
- package/src/editable-artifacts.ts +1 -1
- package/src/index.ts +3578 -1273
- package/src/insights-model-bundle.ts +19 -7
- package/src/insights-usage-bundle.ts +16 -19
- package/src/integration-bindings.ts +2 -7
- package/src/integration-facets.ts +73 -6
- package/src/knowledge-entries.ts +8 -1
- package/src/live-session-attempt.ts +0 -22
- package/src/mcp-account-bindings.ts +12 -0
- package/src/mcp-oauth.ts +26 -0
- package/src/organization-integration-policy.ts +235 -0
- package/src/organization-usage.ts +83 -0
- package/src/plugin-packages.ts +226 -42
- package/src/pr-review.ts +7 -69
- package/src/preference-registry-schema.ts +1 -0
- package/src/provision-roles.ts +50 -37
- package/src/retained-provider-commands.ts +286 -9
- package/src/retired-session-create-metadata.ts +16 -0
- package/src/runtime-posture.ts +217 -13
- package/src/schema.ts +104 -120
- package/src/session-admission-block.ts +29 -0
- package/src/session-attempt-writers.ts +48 -0
- package/src/session-control.ts +21 -5
- package/src/session-event-slices.ts +76 -26
- package/src/session-file-attachments.ts +66 -0
- package/src/session-goal-reports.ts +255 -0
- package/src/session-mcp-approval.ts +30 -0
- package/src/session-message-search.ts +348 -0
- package/src/session-queue-commands.ts +60 -36
- package/src/session-retry.ts +319 -0
- package/src/skill-config-migration.ts +11 -2
- package/src/skill-source-release-impact.ts +33 -0
- package/src/skill-source-release.ts +67 -26
- package/src/skills.ts +44 -6
- package/src/user-resource-authority.ts +0 -56
- package/dist/chunk-6T2GGYWE.js.map +0 -1
- package/dist/chunk-7HMK3B45.js.map +0 -1
- package/dist/chunk-DPONPYJD.js.map +0 -1
- package/dist/chunk-F73UKJY6.js.map +0 -1
- package/dist/chunk-T6YLHJLS.js.map +0 -1
- package/dist/host-mcp-binding-match.d.ts +0 -5
- package/dist/host-mcp-bindings.d.ts +0 -79
- package/dist/host-mcp-resolvers.d.ts +0 -47
- package/dist/host-mcp-task-authority.d.ts +0 -43
- package/dist/host-selection-identity.d.ts +0 -6
- package/dist/pack-components.d.ts +0 -83
- package/dist/pack-installations.d.ts +0 -86
- package/src/host-mcp-binding-match.ts +0 -34
- package/src/host-mcp-bindings.ts +0 -777
- package/src/host-mcp-resolvers.ts +0 -266
- package/src/host-mcp-task-authority.ts +0 -384
- package/src/host-selection-identity.ts +0 -29
- package/src/pack-components.ts +0 -980
- package/src/pack-installations.ts +0 -950
- /package/dist/{chunk-MWMXWHJD.js.map → chunk-7JCDSMX2.js.map} +0 -0
- /package/dist/{chunk-ERKVSPDX.js.map → chunk-LVY33EWL.js.map} +0 -0
- /package/dist/{chunk-T6BWIGWJ.js.map → chunk-RIYHP2WU.js.map} +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
external_exports
|
|
3
|
+
} from "./chunk-4UJCXBR2.js";
|
|
4
|
+
import {
|
|
5
|
+
rawRows,
|
|
6
|
+
rlsContextForWorkspace,
|
|
7
|
+
setSubjectRlsContext,
|
|
8
|
+
withRlsContext
|
|
9
|
+
} from "./chunk-CJI6G254.js";
|
|
10
|
+
|
|
11
|
+
// src/organization-integration-policy.ts
|
|
12
|
+
import {
|
|
13
|
+
OrganizationIntegrationPolicy,
|
|
14
|
+
UpdateOrganizationIntegrationPolicyRequest,
|
|
15
|
+
assertOrganizationIntegrationAllowed
|
|
16
|
+
} from "@opengeni/contracts";
|
|
17
|
+
import { sql } from "drizzle-orm";
|
|
18
|
+
var policyScope = external_exports.object({
|
|
19
|
+
accountId: external_exports.string().uuid().transform((value) => value.toLowerCase())
|
|
20
|
+
});
|
|
21
|
+
var acquisitionScope = policyScope.extend({
|
|
22
|
+
workspaceId: external_exports.string().uuid().transform((value) => value.toLowerCase())
|
|
23
|
+
});
|
|
24
|
+
async function requireReadCommitted(tx) {
|
|
25
|
+
const [isolation] = await rawRows(
|
|
26
|
+
tx,
|
|
27
|
+
sql`select current_setting('transaction_isolation') as level`
|
|
28
|
+
);
|
|
29
|
+
if (isolation?.level !== "read committed") {
|
|
30
|
+
throw new Error("Organization integration policy requires read committed isolation");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function read(tx, scope) {
|
|
34
|
+
const [row] = await rawRows(
|
|
35
|
+
tx,
|
|
36
|
+
sql`select jsonb_build_object('mode', mode, 'allowedIntegrationKeys', allowed_integration_keys, 'revision', revision) as policy from organization_integration_policies where account_id = ${scope.accountId}::uuid`
|
|
37
|
+
);
|
|
38
|
+
return OrganizationIntegrationPolicy.parse(row?.policy ?? {});
|
|
39
|
+
}
|
|
40
|
+
async function withAdministratorSubject(tx, subjectId, use) {
|
|
41
|
+
const [previous] = await rawRows(
|
|
42
|
+
tx,
|
|
43
|
+
sql`select current_setting('opengeni.subject_id', true) as subject`
|
|
44
|
+
);
|
|
45
|
+
await setSubjectRlsContext(tx, subjectId);
|
|
46
|
+
const result = await use();
|
|
47
|
+
const expected = previous?.subject ?? "";
|
|
48
|
+
const [restored] = await rawRows(
|
|
49
|
+
tx,
|
|
50
|
+
sql`select set_config('opengeni.subject_id', ${expected}, true) as subject`
|
|
51
|
+
);
|
|
52
|
+
if (restored?.subject !== expected)
|
|
53
|
+
throw new Error("Integration policy subject scope was not restored");
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
async function getOrganizationIntegrationPolicy(db, inputScope, authorize) {
|
|
57
|
+
const scope = policyScope.parse(inputScope);
|
|
58
|
+
const actor = await authorize();
|
|
59
|
+
if (actor.accountId.toLowerCase() !== scope.accountId || !actor.subjectId)
|
|
60
|
+
throw new Error("Canonical organization administrator required");
|
|
61
|
+
return withRlsContext(
|
|
62
|
+
db,
|
|
63
|
+
{ ...scope, workspaceId: null },
|
|
64
|
+
async (tx) => {
|
|
65
|
+
await requireReadCommitted(tx);
|
|
66
|
+
return withAdministratorSubject(tx, actor.subjectId, async () => {
|
|
67
|
+
await tx.execute(
|
|
68
|
+
sql`select opengeni_private.assert_organization_integration_policy_administrator(${scope.accountId}::uuid, ${actor.subjectId})`
|
|
69
|
+
);
|
|
70
|
+
return read(tx, scope);
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
void 0,
|
|
74
|
+
"none"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
async function updateOrganizationIntegrationPolicy(db, inputScope, input, authorize) {
|
|
78
|
+
const scope = policyScope.parse(inputScope);
|
|
79
|
+
const request = UpdateOrganizationIntegrationPolicyRequest.parse(input);
|
|
80
|
+
const actor = await authorize();
|
|
81
|
+
if (actor.accountId.toLowerCase() !== scope.accountId || !actor.subjectId)
|
|
82
|
+
throw new Error("Canonical organization administrator required");
|
|
83
|
+
return withRlsContext(
|
|
84
|
+
db,
|
|
85
|
+
{ ...scope, workspaceId: null },
|
|
86
|
+
async (tx) => {
|
|
87
|
+
await requireReadCommitted(tx);
|
|
88
|
+
return withAdministratorSubject(tx, actor.subjectId, async () => {
|
|
89
|
+
const [row] = await rawRows(
|
|
90
|
+
tx,
|
|
91
|
+
sql`select opengeni_private.update_organization_integration_policy(${scope.accountId}::uuid, ${actor.subjectId}, ${JSON.stringify(request)}::jsonb) as result`
|
|
92
|
+
);
|
|
93
|
+
return OrganizationIntegrationPolicy.parse(row?.result);
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
void 0,
|
|
97
|
+
"none"
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
async function withOrganizationIntegrationPolicyFence(db, inputScope, run) {
|
|
101
|
+
const requested = acquisitionScope.parse(inputScope);
|
|
102
|
+
const resolved = await rlsContextForWorkspace(db, requested.workspaceId);
|
|
103
|
+
if (resolved.accountId !== requested.accountId)
|
|
104
|
+
throw new Error("Organization integration policy workspace scope invalid");
|
|
105
|
+
const scope = { accountId: resolved.accountId, workspaceId: requested.workspaceId };
|
|
106
|
+
return withRlsContext(
|
|
107
|
+
db,
|
|
108
|
+
scope,
|
|
109
|
+
async (tx) => {
|
|
110
|
+
await requireReadCommitted(tx);
|
|
111
|
+
await tx.execute(
|
|
112
|
+
sql`select pg_advisory_xact_lock_shared(hashtextextended(${`organization-integration-policy:${scope.accountId}`}, 0))`
|
|
113
|
+
);
|
|
114
|
+
const [workspace] = await rawRows(
|
|
115
|
+
tx,
|
|
116
|
+
sql`select id from workspaces where id = ${scope.workspaceId}::uuid and account_id = ${scope.accountId}::uuid`
|
|
117
|
+
);
|
|
118
|
+
if (!workspace) throw new Error("Organization integration policy workspace scope invalid");
|
|
119
|
+
const policy = await read(tx, scope);
|
|
120
|
+
Object.freeze(policy.allowedIntegrationKeys);
|
|
121
|
+
Object.freeze(policy);
|
|
122
|
+
const result = await run(tx, policy);
|
|
123
|
+
const [finalWorkspace] = await rawRows(
|
|
124
|
+
tx,
|
|
125
|
+
sql`select id from workspaces where id = ${scope.workspaceId}::uuid and account_id = ${scope.accountId}::uuid for key share`
|
|
126
|
+
);
|
|
127
|
+
if (!finalWorkspace)
|
|
128
|
+
throw new Error("Organization integration policy workspace scope changed before commit");
|
|
129
|
+
return result;
|
|
130
|
+
},
|
|
131
|
+
void 0,
|
|
132
|
+
"none"
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
async function withOrganizationIntegrationAcquisition(db, inputScope, integrationKeys, acquire) {
|
|
136
|
+
const keys = [...integrationKeys];
|
|
137
|
+
if (!keys.length)
|
|
138
|
+
throw new Error("Acquisition requires at least one trusted integration classification");
|
|
139
|
+
return withOrganizationIntegrationPolicyFence(db, inputScope, async (tx, policy) => {
|
|
140
|
+
const assert = () => {
|
|
141
|
+
for (const key of keys) assertOrganizationIntegrationAllowed(policy, key);
|
|
142
|
+
};
|
|
143
|
+
assert();
|
|
144
|
+
const result = await acquire(tx);
|
|
145
|
+
assert();
|
|
146
|
+
return result;
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export {
|
|
151
|
+
getOrganizationIntegrationPolicy,
|
|
152
|
+
updateOrganizationIntegrationPolicy,
|
|
153
|
+
withOrganizationIntegrationPolicyFence,
|
|
154
|
+
withOrganizationIntegrationAcquisition
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=chunk-ZPJ6V2VG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/organization-integration-policy.ts"],"sourcesContent":["import {\n OrganizationIntegrationPolicy,\n UpdateOrganizationIntegrationPolicyRequest,\n assertOrganizationIntegrationAllowed,\n} from \"@opengeni/contracts\";\nimport { sql } from \"drizzle-orm\";\nimport { z } from \"zod\";\nimport {\n rawRows,\n rlsContextForWorkspace,\n setSubjectRlsContext,\n withRlsContext,\n type Database,\n} from \"./database\";\n\nexport type OrganizationIntegrationPolicyScope = { accountId: string };\nexport type OrganizationIntegrationAcquisitionScope = { accountId: string; workspaceId: string };\nconst policyScope = z.object({\n accountId: z\n .string()\n .uuid()\n .transform((value) => value.toLowerCase()),\n});\nconst acquisitionScope = policyScope.extend({\n workspaceId: z\n .string()\n .uuid()\n .transform((value) => value.toLowerCase()),\n});\n/** Trusted application adapter MUST verify canonical human/local organization-admin\n * provenance or accountScopedApiKeyWorkspaceAuthority (exact account + workspace:admin).\n * This callback is a server dependency, never deserialized request data. The returned\n * subject alone is NOT authentication. DB checks below are live authority fences only.\n */\nexport type AuthorizeOrganizationIntegrationPolicyAdministration = () => Promise<{\n accountId: string;\n subjectId: string;\n}>;\n\nasync function requireReadCommitted(tx: Database): Promise<void> {\n const [isolation] = await rawRows<{ level: string }>(\n tx,\n sql`select current_setting('transaction_isolation') as level`,\n );\n if (isolation?.level !== \"read committed\") {\n throw new Error(\"Organization integration policy requires read committed isolation\");\n }\n}\n\nasync function read(\n tx: Database,\n scope: OrganizationIntegrationPolicyScope,\n): Promise<OrganizationIntegrationPolicy> {\n const [row] = await rawRows<{ policy: unknown }>(\n tx,\n sql`select jsonb_build_object('mode', mode, 'allowedIntegrationKeys', allowed_integration_keys, 'revision', revision) as policy from organization_integration_policies where account_id = ${scope.accountId}::uuid`,\n );\n return OrganizationIntegrationPolicy.parse(row?.policy ?? {});\n}\n\n/** Own only the subject setting this policy operation changes. The enclosing\n * withRlsContext transaction/savepoint restores all settings on failure; on\n * success it restores account/workspace only, so restore our subject explicitly.\n * Do not run restoration after a failed SQL statement in an aborted transaction.\n */\nasync function withAdministratorSubject<T>(\n tx: Database,\n subjectId: string,\n use: () => Promise<T>,\n): Promise<T> {\n const [previous] = await rawRows<{ subject: string | null }>(\n tx,\n sql`select current_setting('opengeni.subject_id', true) as subject`,\n );\n await setSubjectRlsContext(tx, subjectId);\n const result = await use();\n const expected = previous?.subject ?? \"\";\n const [restored] = await rawRows<{ subject: string }>(\n tx,\n sql`select set_config('opengeni.subject_id', ${expected}, true) as subject`,\n );\n if (restored?.subject !== expected)\n throw new Error(\"Integration policy subject scope was not restored\");\n return result;\n}\n\nexport async function getOrganizationIntegrationPolicy(\n db: Database,\n inputScope: OrganizationIntegrationPolicyScope,\n authorize: AuthorizeOrganizationIntegrationPolicyAdministration,\n): Promise<OrganizationIntegrationPolicy> {\n const scope = policyScope.parse(inputScope);\n const actor = await authorize();\n if (actor.accountId.toLowerCase() !== scope.accountId || !actor.subjectId)\n throw new Error(\"Canonical organization administrator required\");\n return withRlsContext(\n db,\n { ...scope, workspaceId: null },\n async (tx) => {\n await requireReadCommitted(tx);\n return withAdministratorSubject(tx, actor.subjectId, async () => {\n // Live authority only: no policy or organization advisory lock on reads.\n await tx.execute(\n sql`select opengeni_private.assert_organization_integration_policy_administrator(${scope.accountId}::uuid, ${actor.subjectId})`,\n );\n return read(tx, scope);\n });\n },\n undefined,\n \"none\",\n );\n}\n\n/** Call before acquiring membership/workspace/credential locks in any enclosing\n * transaction. The SQL operation owns policy-exclusive -> membership -> admin\n * row order; it never locks a workspace and rejects acquisition-lock upgrades.\n */\nexport async function updateOrganizationIntegrationPolicy(\n db: Database,\n inputScope: OrganizationIntegrationPolicyScope,\n input: UpdateOrganizationIntegrationPolicyRequest,\n authorize: AuthorizeOrganizationIntegrationPolicyAdministration,\n): Promise<OrganizationIntegrationPolicy> {\n const scope = policyScope.parse(inputScope);\n const request = UpdateOrganizationIntegrationPolicyRequest.parse(input);\n const actor = await authorize();\n if (actor.accountId.toLowerCase() !== scope.accountId || !actor.subjectId)\n throw new Error(\"Canonical organization administrator required\");\n return withRlsContext(\n db,\n { ...scope, workspaceId: null },\n async (tx) => {\n await requireReadCommitted(tx);\n return withAdministratorSubject(tx, actor.subjectId, async () => {\n const [row] = await rawRows<{ result: unknown }>(\n tx,\n sql`select opengeni_private.update_organization_integration_policy(${scope.accountId}::uuid, ${actor.subjectId}, ${JSON.stringify(request)}::jsonb) as result`,\n );\n return OrganizationIntegrationPolicy.parse(row?.result);\n });\n },\n undefined,\n \"none\",\n );\n}\n\n/** Internal serialization primitive, NOT acquisition authorization. Authenticate\n * the caller normally. A callback may first return an exact completed receipt;\n * before any new claim, uncommitted progress, or commit it MUST assert the trusted\n * integration classification against the supplied runtime-frozen policy snapshot.\n * Do not put network operations or retries inside this transaction.\n *\n * Requires read committed isolation. The shared policy fence precedes EVERY\n * organization-membership, workspace/tenancy, and credential lock. In particular,\n * persistProviderOAuthConnection may take the membership fence inside acquire.\n * Policy writers take exclusive policy -> membership -> live administrator rows,\n * and never workspace rows. Ordinary connection lifecycle writers do not take\n * the policy fence. A caller passing an existing transaction must honor this\n * prefix. Never administer policy inside or after an acquisition in that transaction:\n * the SQL writer rejects shared-to-exclusive upgrades rather than risking deadlock.\n * All final persistence must use tx, never a separate connection. No automatic\n * retries: external effects cannot be rolled back. For slow external preparation,\n * preflight separately and use this guard for final persistence. Existing execution,\n * refresh, credential lifecycle, and cleanup do not belong behind this guard.\n */\nexport async function withOrganizationIntegrationPolicyFence<T>(\n db: Database,\n inputScope: OrganizationIntegrationAcquisitionScope,\n run: (tx: Database, policy: OrganizationIntegrationPolicy) => Promise<T>,\n): Promise<T> {\n const requested = acquisitionScope.parse(inputScope);\n // Non-locking authoritative resolution before any new lock; repeat under the\n // policy fence below so a moved/deleted workspace cannot retain stale scope.\n const resolved = await rlsContextForWorkspace(db, requested.workspaceId);\n if (resolved.accountId !== requested.accountId)\n throw new Error(\"Organization integration policy workspace scope invalid\");\n const scope = { accountId: resolved.accountId, workspaceId: requested.workspaceId };\n return withRlsContext(\n db,\n scope,\n async (tx) => {\n await requireReadCommitted(tx);\n await tx.execute(\n sql`select pg_advisory_xact_lock_shared(hashtextextended(${`organization-integration-policy:${scope.accountId}`}, 0))`,\n );\n // No row lock here: the existing writer owns its canonical membership ->\n // workspace prefix. All policy checks and callback writes share this tx.\n const [workspace] = await rawRows(\n tx,\n sql`select id from workspaces where id = ${scope.workspaceId}::uuid and account_id = ${scope.accountId}::uuid`,\n );\n if (!workspace) throw new Error(\"Organization integration policy workspace scope invalid\");\n const policy = await read(tx, scope);\n Object.freeze(policy.allowedIntegrationKeys);\n Object.freeze(policy);\n const result = await run(tx, policy);\n const [finalWorkspace] = await rawRows(\n tx,\n sql`select id from workspaces where id = ${scope.workspaceId}::uuid and account_id = ${scope.accountId}::uuid for key share`,\n );\n if (!finalWorkspace)\n throw new Error(\"Organization integration policy workspace scope changed before commit\");\n return result;\n },\n undefined,\n \"none\",\n );\n}\n\n/** New acquisitions always assert before effects and before returning to commit.\n * The immutable snapshot stays authoritative through commit: the shared fence\n * excludes policy writers and the SQL writer rejects same-transaction upgrades.\n * Receipt-aware callers instead use withOrganizationIntegrationPolicyFence and\n * assert only after distinguishing completed replay from new workflow progress.\n */\nexport async function withOrganizationIntegrationAcquisition<T>(\n db: Database,\n inputScope: OrganizationIntegrationAcquisitionScope,\n integrationKeys: readonly (string | null)[],\n acquire: (tx: Database) => Promise<T>,\n): Promise<T> {\n // Snapshot classifications before the first await, including workspace lookup.\n const keys = [...integrationKeys];\n if (!keys.length)\n throw new Error(\"Acquisition requires at least one trusted integration classification\");\n return withOrganizationIntegrationPolicyFence(db, inputScope, async (tx, policy) => {\n const assert = () => {\n for (const key of keys) assertOrganizationIntegrationAllowed(policy, key);\n };\n assert();\n const result = await acquire(tx);\n assert();\n return result;\n });\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Durable logical-turn state; checks and quota/account signals never spend this budget. */
|
|
2
|
+
export declare const CODEX_CAPACITY_RECOVERY_KEY = "codexCapacityRecoveryV1";
|
|
3
|
+
export declare const CODEX_CAPACITY_FALSE_RESUMPTION_LIMIT = 10;
|
|
4
|
+
export type CodexCapacityRecovery = {
|
|
5
|
+
falseResumptions: number;
|
|
6
|
+
resumeGeneration: number | null;
|
|
7
|
+
retryNotBefore: string | null;
|
|
8
|
+
};
|
|
9
|
+
export declare function readCodexCapacityRecovery(metadata: Record<string, unknown> | null | undefined): CodexCapacityRecovery;
|
|
10
|
+
/** Equal jitter, 30–60 seconds initially, capped at 15 minutes. Persist the chosen deadline. */
|
|
11
|
+
export declare function codexFalseResumptionBackoffMs(count: number, random?: number): number;
|
|
12
|
+
export declare function clearCodexCapacityRecovery(metadata: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Refusal-specific, ordered recovery evidence; never erase the failure ledger. */
|
|
2
|
+
export declare function unresolvedCodexCredentialFailures(metadata: Record<string, unknown> | null | undefined, accounts: readonly {
|
|
3
|
+
id: string;
|
|
4
|
+
status: string;
|
|
5
|
+
exhaustedUntil: Date | null;
|
|
6
|
+
exhaustedKind: string | null;
|
|
7
|
+
exhaustedRevision?: number;
|
|
8
|
+
credentialVersion?: number;
|
|
9
|
+
}[], now?: Date): string[];
|
|
@@ -1362,12 +1362,13 @@ export declare const companyProfileAgentProposalReceipts: import("drizzle-orm/pg
|
|
|
1362
1362
|
label?: string | null | undefined;
|
|
1363
1363
|
helpText?: string | null | undefined;
|
|
1364
1364
|
skillReview?: {
|
|
1365
|
+
removalOperationId?: string | undefined;
|
|
1365
1366
|
sourceOperationId: string;
|
|
1366
1367
|
skillId: string;
|
|
1367
1368
|
revisionId: string;
|
|
1368
1369
|
expectedRevisionId: string | null;
|
|
1369
1370
|
expectedScopeVersion: number;
|
|
1370
|
-
} | undefined;
|
|
1371
|
+
} | null | undefined;
|
|
1371
1372
|
options: {
|
|
1372
1373
|
id: string;
|
|
1373
1374
|
label: string;
|
|
@@ -1401,12 +1402,13 @@ export declare const companyProfileAgentProposalReceipts: import("drizzle-orm/pg
|
|
|
1401
1402
|
label?: string | null | undefined;
|
|
1402
1403
|
helpText?: string | null | undefined;
|
|
1403
1404
|
skillReview?: {
|
|
1405
|
+
removalOperationId?: string | undefined;
|
|
1404
1406
|
sourceOperationId: string;
|
|
1405
1407
|
skillId: string;
|
|
1406
1408
|
revisionId: string;
|
|
1407
1409
|
expectedRevisionId: string | null;
|
|
1408
1410
|
expectedScopeVersion: number;
|
|
1409
|
-
} | undefined;
|
|
1411
|
+
} | null | undefined;
|
|
1410
1412
|
options: {
|
|
1411
1413
|
id: string;
|
|
1412
1414
|
label: string;
|
|
@@ -20,12 +20,22 @@ export declare class ConnectAttemptNotFoundError extends Error {
|
|
|
20
20
|
}
|
|
21
21
|
/** Caller must establish live workspace/actor authority before this storage
|
|
22
22
|
* seam. RLS scope is a consistency boundary, not proof of authentication. */
|
|
23
|
+
type ConnectBeginIdentity = {
|
|
24
|
+
idempotencyKey: string;
|
|
25
|
+
requestDigest: string;
|
|
26
|
+
returnUrl: string;
|
|
27
|
+
externalContinuation?: ExternalActorContinuation;
|
|
28
|
+
};
|
|
29
|
+
/** Recover only an exact saved begin request, under the caller's live actor
|
|
30
|
+
* admission. This performs no provider work or acquisition. */
|
|
31
|
+
export declare function getConnectBeginReplay(db: Database, scope: ConnectActorScope, input: ConnectBeginIdentity): Promise<Attempt | null>;
|
|
23
32
|
export declare function beginConnectAttempt(db: Database, scope: ConnectActorScope, input: {
|
|
24
33
|
idempotencyKey: string;
|
|
25
34
|
requestDigest: string;
|
|
26
35
|
returnUrl: string;
|
|
27
36
|
attempt: Attempt;
|
|
28
37
|
externalContinuation?: ExternalActorContinuation;
|
|
38
|
+
authorizeAcquisition?: (tx: Database) => Promise<void>;
|
|
29
39
|
}): Promise<Attempt>;
|
|
30
40
|
export declare function getConnectAttempt(db: Database, scope: ConnectActorScope, id: string): Promise<{
|
|
31
41
|
attempt: Attempt;
|
|
@@ -41,6 +51,8 @@ export declare function claimConnectOperation(db: Database, scope: ConnectActorS
|
|
|
41
51
|
operationId: string;
|
|
42
52
|
inputDigest: string;
|
|
43
53
|
authorize?: ConnectOperationAuthorization;
|
|
54
|
+
/** Additional acquisition admission, only after exact no-effect receipt replay. */
|
|
55
|
+
authorizeAcquisition?: (tx: Database, attempt: Attempt) => Promise<void>;
|
|
44
56
|
}): Promise<{
|
|
45
57
|
status: "claimed";
|
|
46
58
|
attempt: Attempt;
|
|
@@ -57,4 +69,7 @@ export declare function finishConnectOperation(db: Database, scope: ConnectActor
|
|
|
57
69
|
inputDigest: string;
|
|
58
70
|
commit: (tx: Database, current: Attempt) => Promise<Attempt>;
|
|
59
71
|
authorize?: ConnectOperationAuthorization;
|
|
72
|
+
/** Additional acquisition admission, only after exact no-effect receipt replay. */
|
|
73
|
+
authorizeAcquisition?: (tx: Database, attempt: Attempt) => Promise<void>;
|
|
60
74
|
}): Promise<Attempt>;
|
|
75
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ConnectAttemptConflictError,
|
|
3
|
+
ConnectAttemptNotFoundError,
|
|
4
|
+
beginConnectAttempt,
|
|
5
|
+
claimConnectOperation,
|
|
6
|
+
finishConnectOperation,
|
|
7
|
+
getConnectAttempt,
|
|
8
|
+
getConnectBeginReplay,
|
|
9
|
+
listPendingConnectAttempts
|
|
10
|
+
} from "./chunk-AJA2ZIUW.js";
|
|
11
|
+
import "./chunk-CJI6G254.js";
|
|
12
|
+
import "./chunk-MN5PZMEK.js";
|
|
13
|
+
import "./chunk-S2TZ3F4L.js";
|
|
14
|
+
import "./chunk-PZ5AY32C.js";
|
|
15
|
+
export {
|
|
16
|
+
ConnectAttemptConflictError,
|
|
17
|
+
ConnectAttemptNotFoundError,
|
|
18
|
+
beginConnectAttempt,
|
|
19
|
+
claimConnectOperation,
|
|
20
|
+
finishConnectOperation,
|
|
21
|
+
getConnectAttempt,
|
|
22
|
+
getConnectBeginReplay,
|
|
23
|
+
listPendingConnectAttempts
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=connect-attempts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -1,71 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type ConnectionKind as ConnectionKindValue
|
|
1
|
+
import { ConnectionUseAttribution, type ConnectionUseDenialReason as ConnectionUseDenialReasonValue } from "@opengeni/contracts/connection-authority";
|
|
2
|
+
import { type ConnectionKind as ConnectionKindValue } from "@opengeni/contracts";
|
|
3
3
|
import { type Database } from "./database.js";
|
|
4
|
-
|
|
4
|
+
/** Called only after the core layer has established the authenticated sender. */
|
|
5
|
+
export declare function listOwnedConnectionAccounts(db: Database, input: {
|
|
5
6
|
accountId: string;
|
|
6
7
|
workspaceId: string;
|
|
7
8
|
subjectId: string;
|
|
8
|
-
}): Promise<
|
|
9
|
-
export declare function issueSelfConnectionUseGrant(db: Database, input: {
|
|
10
|
-
accountId: string;
|
|
11
|
-
workspaceId: string;
|
|
12
|
-
subjectId: string;
|
|
13
|
-
authorityId: string;
|
|
14
|
-
request: IssueConnectionUseGrantRequest;
|
|
15
|
-
}): Promise<{
|
|
16
|
-
grantId: string;
|
|
17
|
-
targetWorkspaceId: string;
|
|
18
|
-
targetSessionId: string | null;
|
|
19
|
-
mode: "always" | "once" | "session";
|
|
20
|
-
context: "user_private" | "workspace_shared";
|
|
21
|
-
authorityEpoch: number | null;
|
|
22
|
-
generation: number;
|
|
23
|
-
status: "active" | "consumed" | "expired" | "revoked";
|
|
24
|
-
expiresAt: string | null;
|
|
25
|
-
delegation: {
|
|
26
|
-
authorityId: string;
|
|
27
|
-
grantId: string;
|
|
28
|
-
organizationId: string;
|
|
29
|
-
workspaceId: string;
|
|
30
|
-
sessionId: string | null;
|
|
31
|
-
action: string;
|
|
32
|
-
mode: "always" | "once" | "session";
|
|
33
|
-
context: "user_private" | "workspace_shared";
|
|
34
|
-
authorityEpoch: number | null;
|
|
35
|
-
authorityGeneration: number;
|
|
36
|
-
grantGeneration: number;
|
|
37
|
-
resourceVersionId?: string | null | undefined;
|
|
38
|
-
};
|
|
39
|
-
action: "connection.use";
|
|
40
|
-
}>;
|
|
41
|
-
export declare function revokeSelfConnectionUseGrant(db: Database, input: {
|
|
42
|
-
accountId: string;
|
|
43
|
-
workspaceId: string;
|
|
44
|
-
subjectId: string;
|
|
45
|
-
grantId: string;
|
|
46
|
-
}): Promise<{
|
|
47
|
-
grantId: string;
|
|
48
|
-
generation: number;
|
|
49
|
-
status: "revoked";
|
|
50
|
-
revokedAt: string;
|
|
51
|
-
}>;
|
|
52
|
-
/**
|
|
53
|
-
* Resolves the immutable physical origin for one explicit common-user
|
|
54
|
-
* connection selection. The SECURITY DEFINER database boundary proves the
|
|
55
|
-
* owning human, active organization membership, target-workspace access, and
|
|
56
|
-
* exact authority/grant generations without exposing credentials or allowing
|
|
57
|
-
* an ambient cross-workspace inventory.
|
|
58
|
-
*/
|
|
59
|
-
export declare function resolvePersonalConnectionAuthoritySelectionOrigin(db: Database, input: {
|
|
60
|
-
accountId: string;
|
|
61
|
-
targetWorkspaceId: string;
|
|
62
|
-
subjectId: string;
|
|
9
|
+
}): Promise<Array<{
|
|
63
10
|
connectionId: string;
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
export declare function resolveConnectionUseAuthority(db: Database, input: {
|
|
67
|
-
snapshot: unknown;
|
|
68
|
-
}): Promise<ConnectionUseAuthorizationResult>;
|
|
11
|
+
originWorkspaceId: string;
|
|
12
|
+
}>>;
|
|
69
13
|
export type AcceptedConnectionUseContext = {
|
|
70
14
|
accountId: string;
|
|
71
15
|
workspaceId: string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type Database } from "./database.js";
|
|
2
|
+
import type { ConnectionCredentialForBroker } from "./connection-token-resolver.js";
|
|
3
|
+
/** Serialize rotating-token exchange across workers, not only within one process. */
|
|
4
|
+
export declare function withConnectionRefreshLock<T>(db: Database, credential: ConnectionCredentialForBroker, work: (lockedDb: Database) => Promise<T>): Promise<T>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { environmentsEncryptionKeyBytes, type McpServerConnectionRef, type Settings } from "@opengeni/config";
|
|
2
|
-
import type { ConnectionCredentialPlacement, ConnectionKind,
|
|
3
|
-
import { type ConnectionUseAttribution
|
|
2
|
+
import type { ConnectionCredentialPlacement, ConnectionKind, ConnectionStatus, McpConnectionResourceScope, McpCredentialAuthNeededReason } from "@opengeni/contracts";
|
|
3
|
+
import { type ConnectionUseAttribution } from "@opengeni/contracts/connection-authority";
|
|
4
4
|
import { type DnsLookup, type FetchLike } from "@opengeni/network";
|
|
5
5
|
export { isPrivateAddress } from "@opengeni/network";
|
|
6
6
|
import { encryptEnvironmentValue } from "./environment-crypto.js";
|
|
7
7
|
import type { Database } from "./database.js";
|
|
8
|
+
import { withConnectionRefreshLock } from "./connection-refresh-lock.js";
|
|
8
9
|
import type { AcceptedConnectionUseContext, AcceptedConnectionUseResolution } from "./connection-authority.js";
|
|
9
10
|
export type ConnectionCredentialForBroker = {
|
|
10
11
|
id: string;
|
|
@@ -99,59 +100,23 @@ export type ResolveConnectionCredentialInput = {
|
|
|
99
100
|
credentialResolutionMode?: "execution" | "preflight";
|
|
100
101
|
/** Frozen provider authority generation captured by the calling integration/catalog. */
|
|
101
102
|
expectedAuthorityGeneration?: number;
|
|
102
|
-
/**
|
|
103
|
-
|
|
103
|
+
/** Attribution already authorized for forwarding to a host resolver; never authorizes local use. */
|
|
104
|
+
hostConnectionUseAttribution?: ConnectionUseAttribution;
|
|
104
105
|
/** Exact accepted attempt plus one stable physical-provider request id. */
|
|
105
106
|
connectionUseContext?: AcceptedConnectionUseContext;
|
|
106
107
|
};
|
|
107
|
-
export
|
|
108
|
-
accountId: string;
|
|
109
|
-
workspaceId: string;
|
|
110
|
-
sessionId: string;
|
|
111
|
-
rootSessionId: string;
|
|
112
|
-
turnId: string;
|
|
113
|
-
attemptId: string | null;
|
|
114
|
-
executionGeneration: number;
|
|
115
|
-
initiator: TurnInitiator;
|
|
116
|
-
initiatorContext: TurnInitiatorContext;
|
|
117
|
-
surface: McpCredentialsRequest["surface"];
|
|
118
|
-
/** Backend-owned attempt liveness, independent of binding delegation. */
|
|
119
|
-
authorizeExecution?: (request: McpCredentialsRequest) => Promise<boolean>;
|
|
120
|
-
/** Backend-owned live validator. Never populate from caller JSON or a host
|
|
121
|
-
* credential response. Omission denies every explicit durable reference. */
|
|
122
|
-
authorizeDurableBinding?: (request: McpCredentialsRequest) => Promise<boolean>;
|
|
123
|
-
/** Backend-only accepted-work lookup, not a host response or registry fallback. */
|
|
124
|
-
resolveAcceptedBinding?: (request: McpCredentialsRequest) => Promise<McpServerConnectionRef | null>;
|
|
125
|
-
};
|
|
126
|
-
export declare class HostMcpCredentialScopeError extends Error {
|
|
127
|
-
constructor(field: "accountId" | "workspaceId" | "sessionId");
|
|
128
|
-
}
|
|
129
|
-
export declare class HostMcpCredentialBindingError extends Error {
|
|
130
|
-
constructor(field: "provider" | "providerDomain" | "connectionId" | "scopes" | "resource" | "selectedResources" | "destinationUrl" | "credentialPlacements");
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Adapts the public embedding credential port to the runtime's connection
|
|
134
|
-
* resolver contract. Scope echoes are checked before credential headers can
|
|
135
|
-
* reach a request; the returned object is a fresh copy so a host cannot mutate
|
|
136
|
-
* headers after resolution.
|
|
137
|
-
*/
|
|
138
|
-
export declare function buildHostConnectionTokenResolver(resolve: NonNullable<ConnectionCredentialsPort["mcpCredentials"]>, suppliedContext: HostMcpCredentialResolverContext): (input: ResolveConnectionCredentialInput) => Promise<ResolveConnectionCredentialResult>;
|
|
139
|
-
/** Authenticated request-time adapter. No synthetic session/turn authority and
|
|
140
|
-
* no durable binding admission; every physical use must retain live API proof. */
|
|
141
|
-
export declare function buildHostGatewayConnectionTokenResolver(resolve: NonNullable<ConnectionCredentialsPort["mcpGatewayCredentials"]>, suppliedContext: Pick<McpGatewayCredentialsRequest, "accountId" | "workspaceId" | "authority">, reauthorize: () => Promise<void>): (input: ResolveConnectionCredentialInput) => Promise<ResolveConnectionCredentialResult>;
|
|
142
|
-
export declare function normalizedHostCredentialHeaders(headers: Record<string, string>, allowEmpty?: boolean): Record<string, string>;
|
|
108
|
+
export declare function normalizedCredentialHeaders(headers: Record<string, string>, allowEmpty?: boolean): Record<string, string>;
|
|
143
109
|
export type ConnectionBrokerDeps = {
|
|
144
110
|
loadCredential: (db: Database, settings: Settings, input: ConnectionCredentialLookupInput) => Promise<ConnectionCredentialForBroker | null>;
|
|
145
111
|
recordRefresh: (db: Database, input: ConnectionTokenRefreshInput) => Promise<boolean>;
|
|
146
112
|
setStatus: (db: Database, workspaceId: string, status: ConnectionStatus, lastError: string | null, guard: ConnectionStatusGuard) => Promise<boolean>;
|
|
147
113
|
recordUsed: (db: Database, workspaceId: string, connectionId: string, subjectId?: string | null) => Promise<void>;
|
|
148
114
|
refresh: typeof refreshOAuthConnectionCredential;
|
|
115
|
+
/** Test/adapter seam; standalone defaults to the database-backed refresh lock. */
|
|
116
|
+
withRefreshLock?: typeof withConnectionRefreshLock;
|
|
149
117
|
encrypt: typeof encryptEnvironmentValue;
|
|
150
118
|
keyBytes: typeof environmentsEncryptionKeyBytes;
|
|
151
119
|
now: () => Date;
|
|
152
|
-
authorizeUse?: (db: Database, input: {
|
|
153
|
-
snapshot: unknown;
|
|
154
|
-
}) => Promise<ConnectionUseAuthorizationResult>;
|
|
155
120
|
authorizeAcceptedUse?: (db: Database, input: AcceptedConnectionUseContext & {
|
|
156
121
|
serverId: string;
|
|
157
122
|
connectionId?: string;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type DatabaseTimingStage = "transaction_admission" | "savepoint_admission" | "rls_setup" | "scoped_callback";
|
|
2
|
+
export type DatabaseTimingObservation = {
|
|
3
|
+
stage: DatabaseTimingStage;
|
|
4
|
+
outcome: "completed" | "failed";
|
|
5
|
+
durationMs: number;
|
|
6
|
+
};
|
|
7
|
+
export type DatabaseTimingObserver = (observation: DatabaseTimingObservation) => void;
|
|
8
|
+
/** Opt-in, async-local diagnostics only; no identity or query payload is retained. */
|
|
9
|
+
export declare function withDatabaseTimingObserver<T>(observer: DatabaseTimingObserver, work: () => Promise<T>): Promise<T>;
|
|
10
|
+
export declare function startDatabaseTiming(stage: DatabaseTimingStage): (outcome: DatabaseTimingObservation["outcome"]) => void;
|
package/dist/database.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SessionAttachmentReadAccess } from "./session-file-attachments.js";
|
|
1
2
|
import { type SQL } from "drizzle-orm";
|
|
2
3
|
import type { PgDatabase, PgTransactionConfig } from "drizzle-orm/pg-core";
|
|
3
4
|
import postgres from "postgres";
|
|
@@ -22,11 +23,14 @@ export type RlsContext = {
|
|
|
22
23
|
workspaceId?: string | null;
|
|
23
24
|
};
|
|
24
25
|
export type SessionRlsActorContext = {
|
|
26
|
+
/** Server-authorized session attachment scope; never taken from request JSON. */
|
|
27
|
+
sessionAttachmentReadAccess?: SessionAttachmentReadAccess;
|
|
25
28
|
subjectId: string;
|
|
26
29
|
/** Host-verified personal file ownership, never a request-supplied subject. */
|
|
27
30
|
privateFileOwnerSubjectId?: string | null;
|
|
28
31
|
initiatingHumanSubjectId?: string | null;
|
|
29
32
|
};
|
|
33
|
+
export declare function currentSessionAttachmentReadAccess(): SessionAttachmentReadAccess | undefined;
|
|
30
34
|
export declare function withSessionRlsActorContext<T>(actor: SessionRlsActorContext, fn: () => Promise<T>): Promise<T>;
|
|
31
35
|
/**
|
|
32
36
|
* RLS posture for the connection OpenGeni's query layer runs over (Step I, §7.7).
|
|
@@ -607,4 +607,13 @@ export declare class PostgresEditableArtifactLiveReadStore {
|
|
|
607
607
|
}): Promise<void>;
|
|
608
608
|
private readVerifiedSnapshotBytes;
|
|
609
609
|
}
|
|
610
|
+
export declare function transactionallyAuthorizeEditableArtifactActor(tx: Database, input: Readonly<{
|
|
611
|
+
scope: PersistedEditableArtifactScope;
|
|
612
|
+
artifactId: string;
|
|
613
|
+
actor: PersistedEditableArtifactActor;
|
|
614
|
+
permission: "create" | "import" | "read" | "edit" | "manage";
|
|
615
|
+
}>): Promise<Readonly<{
|
|
616
|
+
allowed: boolean;
|
|
617
|
+
revision: number;
|
|
618
|
+
}>>;
|
|
610
619
|
export {};
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
PostgresEditableArtifactLiveTicketStore,
|
|
8
8
|
PostgresEditableArtifactStore,
|
|
9
9
|
listEditableArtifactIdsForSession,
|
|
10
|
-
touchEditableArtifactSessionLink
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import "./chunk-
|
|
10
|
+
touchEditableArtifactSessionLink,
|
|
11
|
+
transactionallyAuthorizeEditableArtifactActor
|
|
12
|
+
} from "./chunk-SYKHLPTK.js";
|
|
13
|
+
import "./chunk-CJI6G254.js";
|
|
14
|
+
import "./chunk-MN5PZMEK.js";
|
|
14
15
|
import "./chunk-S2TZ3F4L.js";
|
|
15
16
|
import "./chunk-PZ5AY32C.js";
|
|
16
17
|
export {
|
|
@@ -22,6 +23,7 @@ export {
|
|
|
22
23
|
PostgresEditableArtifactLiveTicketStore,
|
|
23
24
|
PostgresEditableArtifactStore,
|
|
24
25
|
listEditableArtifactIdsForSession,
|
|
25
|
-
touchEditableArtifactSessionLink
|
|
26
|
+
touchEditableArtifactSessionLink,
|
|
27
|
+
transactionallyAuthorizeEditableArtifactActor
|
|
26
28
|
};
|
|
27
29
|
//# sourceMappingURL=editable-artifacts.js.map
|