@opengeni/core 1.3.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
  2. package/dist/application/modal-native-original-configuration.d.ts +79 -0
  3. package/dist/domain/capabilities.d.ts +1 -0
  4. package/dist/domain/connector-tool-permissions.d.ts +1 -1
  5. package/dist/domain/realtime-voice-billing.d.ts +95 -0
  6. package/dist/domain/scheduled-task-access.d.ts +2 -2
  7. package/dist/domain/scheduled-tasks.d.ts +2 -2
  8. package/dist/domain/session-connection-accounts.d.ts +1 -1
  9. package/dist/domain/session-start-timing.d.ts +1 -1
  10. package/dist/domain/session-tool-policy.d.ts +11 -7
  11. package/dist/domain/voice-input-billing.d.ts +77 -0
  12. package/dist/domain/web-search-billing.d.ts +45 -0
  13. package/dist/goal-admission.d.ts +24 -0
  14. package/dist/index.d.ts +3 -0
  15. package/dist/index.js +1065 -365
  16. package/dist/index.js.map +1 -1
  17. package/dist/transcription.d.ts +119 -2
  18. package/package.json +12 -12
  19. package/src/application/modal-native-live-declaration-join.ts +196 -0
  20. package/src/application/modal-native-original-configuration.ts +261 -0
  21. package/src/default-session-model.ts +58 -88
  22. package/src/domain/capabilities.ts +44 -2
  23. package/src/domain/connector-tool-permissions.ts +24 -8
  24. package/src/domain/realtime-voice-billing.ts +400 -0
  25. package/src/domain/scheduled-task-access.ts +2 -1
  26. package/src/domain/scheduled-tasks.ts +3 -2
  27. package/src/domain/session-connection-accounts.ts +7 -3
  28. package/src/domain/session-start-timing.ts +5 -0
  29. package/src/domain/session-tool-policy.ts +20 -4
  30. package/src/domain/sessions.ts +145 -98
  31. package/src/domain/voice-input-billing.ts +315 -0
  32. package/src/domain/web-search-billing.ts +154 -0
  33. package/src/index.ts +3 -0
  34. package/src/model-catalog.ts +32 -38
  35. package/src/sandbox/routing.ts +59 -25
  36. package/src/transcription.ts +122 -3
@@ -1,4 +1,6 @@
1
+ import type { VoiceInputPricing, VoiceInputUsage } from "@opengeni/config";
1
2
  import type { TranscribeAudioResponse, VoiceInputErrorCode } from "@opengeni/contracts";
3
+ import type { CreditDebitAttribution } from "@opengeni/db";
2
4
  /**
3
5
  * Server-owned upstream budget for one provider attempt. Resumable recording
4
6
  * claims remain fenced for longer than this budget before another worker may
@@ -31,21 +33,112 @@ export type TranscriptionRequest = {
31
33
  preferredProvider?: string | null | undefined;
32
34
  fallbackEnabled?: boolean | undefined;
33
35
  excludedProviders?: readonly string[] | undefined;
36
+ /**
37
+ * Credit settlement facts for a deployment-funded provider. Required when
38
+ * the selected provider is deployment-funded and credit billing is active;
39
+ * the service fails closed without it.
40
+ */
41
+ billing?: TranscriptionBillingContext | undefined;
42
+ /**
43
+ * Internal: return `settleBilling` instead of settling before returning, so
44
+ * a resumable segment's transcript commits before any billing write.
45
+ */
46
+ deferBillingSettlement?: boolean;
47
+ };
48
+ /**
49
+ * Trusted, server-built settlement identity for one transcription unit. The
50
+ * usage receipt and debit idempotency keys derive from `workspaceId` +
51
+ * `sourceId` (see `voiceInputSettlementKeys`), so a retry or a later
52
+ * reconciliation settles the same unit exactly once.
53
+ */
54
+ export type TranscriptionBillingContext = {
55
+ /**
56
+ * Server-derived unit identity. Never a client-chosen value: a reused id
57
+ * settles once, so a client-controlled id would make later calls free.
58
+ */
59
+ sourceId: string;
60
+ /** Trusted payer facts from the authenticated request boundary. */
61
+ attribution: CreditDebitAttribution;
62
+ /**
63
+ * Audio duration measured by the server from WAV bytes it produced (the
64
+ * resumable segment, or the normalized one-shot upload). Bills whenever the
65
+ * provider reports no usage this deployment has a price for.
66
+ */
67
+ trustedDurationSeconds?: number | undefined;
34
68
  };
35
69
  export type TranscriptionResult = TranscribeAudioResponse & {
36
70
  /** Server-private provider id for operational metrics only. Never returned to clients. */
37
71
  providerId: string;
38
72
  audioSeconds: number;
39
73
  latencyMs: number;
74
+ /** Opengeni credits charged for this call (0 for subscription/free providers). */
75
+ creditCostMicros?: number | undefined;
76
+ /**
77
+ * Server-only settlement callback; never serialized into a public response.
78
+ * Never rejects: a settlement failure after provider success is logged and
79
+ * retried, and the transcript is still delivered.
80
+ */
81
+ settleBilling?: () => Promise<void>;
82
+ };
83
+ export type TranscriptionBillingRefusalCode = "insufficient_credits" | "allowance_exhausted" | "monthly_model_cost_limit";
84
+ /**
85
+ * Pre-use refusal for deployment-funded transcription: 402 for credits and
86
+ * allowances (same codes as session admission), 429 for a static monthly cap.
87
+ */
88
+ export declare class TranscriptionBillingRefusedError extends Error {
89
+ readonly status: 402 | 429;
90
+ readonly code: TranscriptionBillingRefusalCode;
91
+ readonly details: {
92
+ scope?: string;
93
+ resetsAt?: string | null;
94
+ subjectId?: string;
95
+ };
96
+ constructor(input: {
97
+ code: TranscriptionBillingRefusalCode;
98
+ message: string;
99
+ details?: {
100
+ scope?: string;
101
+ resetsAt?: string | null;
102
+ subjectId?: string;
103
+ };
104
+ });
105
+ }
106
+ /**
107
+ * Credit admission and settlement for deployment-funded transcription.
108
+ * Subscription providers (Codex, SuperGrok) never reach this port.
109
+ */
110
+ export type TranscriptionBilling = {
111
+ /** Refuse before any audio is sent when the payer cannot fund the call. */
112
+ admit(input: {
113
+ accountId: string;
114
+ workspaceId: string;
115
+ attribution: CreditDebitAttribution;
116
+ }): Promise<void>;
117
+ /**
118
+ * Record usage and debit credits once per unit, after use. The usage receipt
119
+ * commits before the debit, so a failed debit leaves a durable receipt that
120
+ * `admit` reconciles on the workspace's next voice request.
121
+ */
122
+ settle(input: {
123
+ accountId: string;
124
+ workspaceId: string;
125
+ providerId: string;
126
+ model: string;
127
+ pricing: VoiceInputPricing;
128
+ usage: VoiceInputUsage | null;
129
+ billing: TranscriptionBillingContext;
130
+ }): Promise<{
131
+ creditCostMicros: number;
132
+ }>;
40
133
  };
41
134
  export declare class TranscriptionServiceError extends Error {
42
- readonly code: VoiceInputErrorCode;
135
+ readonly code: Exclude<VoiceInputErrorCode, TranscriptionBillingRefusalCode>;
43
136
  readonly status: number;
44
137
  readonly retryable: boolean;
45
138
  /** Explicit rejection before any transcription result; safe to try another provider. */
46
139
  readonly fallbackSafe: boolean;
47
140
  constructor(input: {
48
- code: VoiceInputErrorCode;
141
+ code: Exclude<VoiceInputErrorCode, TranscriptionBillingRefusalCode>;
49
142
  message: string;
50
143
  status?: number;
51
144
  retryable?: boolean;
@@ -73,6 +166,15 @@ export type TranscriptionProvider = {
73
166
  /** The adapter guarantees that its upstream transport honors AbortSignal. */
74
167
  readonly supportsServerDeadline: true;
75
168
  readonly experimental?: boolean | undefined;
169
+ /**
170
+ * Present when the deployment pays the upstream provider (OpenAI/Azure):
171
+ * the call is admitted against and settled in Opengeni credits. Absent for
172
+ * the workspace's own subscriptions, which are never charged.
173
+ */
174
+ readonly deploymentFunded?: {
175
+ readonly model: string;
176
+ readonly pricing: VoiceInputPricing | null;
177
+ } | undefined;
76
178
  /**
77
179
  * Deployment readiness when called without a workspace. When `workspaceId` is
78
180
  * provided, providers may require a workspace-attached credential (e.g. Codex).
@@ -90,14 +192,27 @@ export type TranscriptionProvider = {
90
192
  }): Promise<{
91
193
  text: string;
92
194
  languages: string[];
195
+ usage?: VoiceInputUsage | null | undefined;
93
196
  }>;
94
197
  };
95
198
  export type TranscriptionService = {
96
199
  limits(): TranscriptionLimits;
97
200
  /** True when at least one ready provider can serve requests. */
98
201
  available(context?: TranscriptionAvailabilityContext): boolean | Promise<boolean>;
202
+ availableProviderIds?(context: TranscriptionAvailabilityContext): Promise<string[]>;
99
203
  /** Select one provider before a durable segment attempt; retries pin this id. */
100
204
  selectProvider?(context: TranscriptionAvailabilityContext): string | null | Promise<string | null>;
205
+ /**
206
+ * Credit admission for an exact provider before durable work is claimed.
207
+ * Resolves for subscription providers; throws TranscriptionBillingRefusedError
208
+ * when a deployment-funded provider cannot be paid for.
209
+ */
210
+ admit?(input: {
211
+ providerId: string;
212
+ accountId: string;
213
+ workspaceId: string;
214
+ attribution: CreditDebitAttribution;
215
+ }): Promise<void>;
101
216
  transcribe(request: TranscriptionRequest): Promise<TranscriptionResult>;
102
217
  };
103
218
  export type PreparedTranscriptionSegment = {
@@ -113,6 +228,8 @@ export type TranscriptionSegmenter = {
113
228
  sourceMimeType: string;
114
229
  totalDurationMilliseconds: number;
115
230
  providerSegmentSeconds: number;
231
+ /** Hard decode ceiling (`ffmpeg -t`); audio past it is never decoded. */
232
+ maxDecodeSeconds?: number | undefined;
116
233
  chunks: AsyncIterable<Uint8Array>;
117
234
  signal?: AbortSignal | undefined;
118
235
  }): AsyncIterable<PreparedTranscriptionSegment>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/core",
3
- "version": "1.3.0",
3
+ "version": "1.4.2",
4
4
  "description": "OpenGeni framework-agnostic core: the domain, access, and billing layers (neutral access, off-HTTP V2 surface). Behavior-preserving extraction from apps/api — keeps Hono's HTTPException for error throwing (typed-errors cleanup deferred).",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -50,17 +50,17 @@
50
50
  },
51
51
  "dependencies": {
52
52
  "@modelcontextprotocol/sdk": "^1.29.0",
53
- "@opengeni/capabilities": "1.3.0",
54
- "@opengeni/codex": "1.3.0",
55
- "@opengeni/config": "1.3.0",
56
- "@opengeni/contracts": "1.3.0",
57
- "@opengeni/db": "1.3.0",
58
- "@opengeni/documents": "1.3.0",
59
- "@opengeni/events": "1.3.0",
60
- "@opengeni/network": "1.3.0",
61
- "@opengeni/observability": "1.3.0",
62
- "@opengeni/runtime": "1.3.0",
63
- "@opengeni/storage": "1.3.0",
53
+ "@opengeni/capabilities": "1.4.2",
54
+ "@opengeni/codex": "1.4.2",
55
+ "@opengeni/config": "1.4.2",
56
+ "@opengeni/contracts": "1.4.2",
57
+ "@opengeni/db": "1.4.2",
58
+ "@opengeni/documents": "1.4.2",
59
+ "@opengeni/events": "1.4.2",
60
+ "@opengeni/network": "1.4.2",
61
+ "@opengeni/observability": "1.4.2",
62
+ "@opengeni/runtime": "1.4.2",
63
+ "@opengeni/storage": "1.4.2",
64
64
  "hono": "^4.12.18",
65
65
  "zod": "^4.2.1"
66
66
  },
@@ -0,0 +1,196 @@
1
+ import { types } from "node:util";
2
+ import type { Settings } from "@opengeni/config";
3
+ import { ModalNativePreparationDeclarationV2 } from "@opengeni/contracts/modal-native-proof-v2";
4
+ import {
5
+ lockLiveNativeOriginalOriginTx,
6
+ type Database,
7
+ type ModalNativeLiveOriginProjection,
8
+ type ModalNativeLiveOriginResult,
9
+ } from "@opengeni/db";
10
+ import { z } from "zod";
11
+ import {
12
+ currentNativeOriginalConfigurationMatches,
13
+ disposeNativeOriginalConfigurationSample,
14
+ sampleNativeOriginalConfiguration,
15
+ type NativeOriginalConfigurationSample,
16
+ } from "./modal-native-original-configuration";
17
+ import {
18
+ configuredNativeWorkerHostTransport,
19
+ disposeNativeWorkerHostTransport,
20
+ nativeWorkerHostTransportDescription,
21
+ verifyNativeWorkerHostTransport,
22
+ } from "./modal-native-worker-host-transport";
23
+
24
+ // Unused PRIVATE request/data join. NOT the canonical claimed-worker issuer,
25
+ // custody authorizer, committed grant, native context or one-use effect permit.
26
+ // No consumer may turn this data into authority from its type/shape alone.
27
+ // A future canonical host entry must establish its actual worker provenance and
28
+ // atomically consume this join with protected declaration/config/grant/cold
29
+ // insertion in this SAME transaction, before any provider-prefix I/O.
30
+ const MAX_BODY_BYTES = 4 * 1024 * 1024;
31
+ const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);
32
+ const nativeLength = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteLength")!.get!;
33
+ const nativeOffset = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteOffset")!.get!;
34
+ const nativeBuffer = Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer")!.get!;
35
+ const request = z
36
+ .object({
37
+ protocol: z.literal("opengeni-modal-native-live-declaration-join"),
38
+ version: z.literal(2),
39
+ requestId: z.string().uuid(),
40
+ workflowId: z.string().min(1).max(1024),
41
+ workflowRunId: z.string().min(1).max(1024),
42
+ activityId: z.string().min(1).max(1024),
43
+ initiatingHumanSubjectId: z
44
+ .string()
45
+ .regex(/^user:.+/u)
46
+ .max(1024),
47
+ declarationJson: z.string().min(1).max(MAX_BODY_BYTES),
48
+ })
49
+ .strict();
50
+
51
+ type JoinSettings = Pick<
52
+ Settings,
53
+ | "delegationSecret"
54
+ | "modalTokenId"
55
+ | "modalTokenSecret"
56
+ | "modalEnvironment"
57
+ | "environmentsEncryptionKey"
58
+ >;
59
+
60
+ /** Sensitive request-local data only. Do not publish/log/cache across commit.
61
+ * The sample contains immutable credential strings which disposal cannot erase.
62
+ * This result has no native-I/O, replay, custody or effect authority. */
63
+ export type NativeLiveDeclarationJoin = Readonly<{
64
+ requestId: string;
65
+ declaration: ModalNativePreparationDeclarationV2;
66
+ projection: ModalNativeLiveOriginProjection;
67
+ configuration: NativeOriginalConfigurationSample;
68
+ }>;
69
+ export type NativeLiveDeclarationJoinResult =
70
+ | { kind: "joined_data"; data: NativeLiveDeclarationJoin }
71
+ | { kind: "off" }
72
+ | { kind: "refused" }
73
+ | Exclude<ModalNativeLiveOriginResult, { kind: "live" }>;
74
+
75
+ function ownedBody(input: Uint8Array): Buffer | null {
76
+ if (!input || types.isProxy(input) || !types.isUint8Array(input)) return null;
77
+ try {
78
+ const length = nativeLength.call(input) as number;
79
+ const backing = nativeBuffer.call(input) as ArrayBuffer;
80
+ if (length > MAX_BODY_BYTES || !types.isArrayBuffer(backing)) return null;
81
+ return Buffer.from(new Uint8Array(backing, nativeOffset.call(input) as number, length));
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
86
+
87
+ function freezeJson<T>(value: T): T {
88
+ if (value && typeof value === "object") {
89
+ for (const child of Object.values(value)) freezeJson(child);
90
+ Object.freeze(value);
91
+ }
92
+ return value;
93
+ }
94
+
95
+ /** Own bytes BEFORE either verifying or parsing. After the blocking SQL join,
96
+ * re-read the explicit CURRENT deployment root/profile and reverify current
97
+ * expiry over those SAME owned bytes. A historical MAC witness is insufficient.
98
+ * No tenant/subject GUC change, general access-token resolver, provider await,
99
+ * fallback, registration or error-to-success conversion occurs here.
100
+ *
101
+ * Input execution/human fields are signed CORRELATION, not caller authority:
102
+ * compare them to the exact DB-derived accepted original projection. This does
103
+ * NOT independently prove that the canonical worker produced the request.
104
+ * Enter an existing scoped transaction before any tenancy/control/row lock;
105
+ * consume the result in that transaction and dispose its sample afterward. */
106
+ export async function lockNativeLiveDeclarationJoinTx(
107
+ scopedTx: Database,
108
+ settings: JoinSettings,
109
+ envelope: string,
110
+ inputBody: Uint8Array,
111
+ ): Promise<NativeLiveDeclarationJoinResult> {
112
+ const initialTransport = configuredNativeWorkerHostTransport(settings);
113
+ if (!initialTransport) return { kind: "off" };
114
+ let body: Buffer | null = null;
115
+ let sample: NativeOriginalConfigurationSample | null = null;
116
+ let retained = false;
117
+ try {
118
+ body = ownedBody(inputBody);
119
+ if (!body) return { kind: "refused" };
120
+ const proof = verifyNativeWorkerHostTransport(initialTransport, envelope, body);
121
+ if (!proof) return { kind: "refused" };
122
+ const description = nativeWorkerHostTransportDescription(initialTransport, proof);
123
+ if (description.action !== "declare_preparation") return { kind: "refused" };
124
+ let parsed: z.infer<typeof request>;
125
+ try {
126
+ parsed = request.parse(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(body)));
127
+ } catch {
128
+ return { kind: "refused" };
129
+ }
130
+ const declarationBytes = Buffer.from(parsed.declarationJson, "utf8");
131
+ let declaration: ModalNativePreparationDeclarationV2;
132
+ try {
133
+ declaration = ModalNativePreparationDeclarationV2.parse(JSON.parse(parsed.declarationJson));
134
+ if (
135
+ parsed.requestId !== description.requestId ||
136
+ Object.keys(declaration.scope).some(
137
+ (key) =>
138
+ declaration.scope[key as keyof typeof declaration.scope] !==
139
+ description.scope[key as keyof typeof description.scope],
140
+ ) ||
141
+ declaration.configurationCaptureRef.id !== description.configurationCaptureRef.id ||
142
+ declaration.configurationCaptureRef.revision !==
143
+ description.configurationCaptureRef.revision ||
144
+ declaration.proofGrantRef.id !== description.proofGrantRef.id ||
145
+ declaration.proofGrantRef.epoch !== description.proofGrantRef.epoch
146
+ )
147
+ return { kind: "refused" };
148
+ sample = sampleNativeOriginalConfiguration(settings, declarationBytes);
149
+ if (!sample) return { kind: "off" };
150
+ } catch {
151
+ return { kind: "refused" };
152
+ } finally {
153
+ declarationBytes.fill(0);
154
+ }
155
+
156
+ const origin = await lockLiveNativeOriginalOriginTx(scopedTx, declaration.scope);
157
+ if (origin.kind !== "live") return origin;
158
+ const currentTransport = configuredNativeWorkerHostTransport(settings);
159
+ if (!currentTransport) return { kind: "refused" };
160
+ try {
161
+ if (
162
+ !verifyNativeWorkerHostTransport(currentTransport, envelope, body) ||
163
+ !currentNativeOriginalConfigurationMatches(sample, settings)
164
+ )
165
+ return { kind: "refused" };
166
+ } finally {
167
+ disposeNativeWorkerHostTransport(currentTransport);
168
+ }
169
+ const projection = origin.projection;
170
+ if (
171
+ Object.keys(declaration.scope).some(
172
+ (key) =>
173
+ declaration.scope[key as keyof typeof declaration.scope] !==
174
+ projection.scope[key as keyof typeof projection.scope],
175
+ ) ||
176
+ projection.initiator.initiatingHumanSubjectId !== parsed.initiatingHumanSubjectId ||
177
+ projection.execution.workflowId !== parsed.workflowId ||
178
+ projection.execution.workflowRunId !== parsed.workflowRunId ||
179
+ projection.execution.activityId !== parsed.activityId ||
180
+ projection.providerRecoveryCount !== declaration.providerRecoveryCount
181
+ )
182
+ return { kind: "refused" };
183
+ const data = Object.freeze({
184
+ requestId: parsed.requestId,
185
+ declaration: freezeJson(declaration),
186
+ projection: freezeJson(structuredClone(projection)),
187
+ configuration: sample,
188
+ });
189
+ retained = true;
190
+ return { kind: "joined_data", data };
191
+ } finally {
192
+ body?.fill(0);
193
+ disposeNativeWorkerHostTransport(initialTransport);
194
+ if (!retained && sample) disposeNativeOriginalConfigurationSample(sample);
195
+ }
196
+ }
@@ -0,0 +1,261 @@
1
+ import { createHash, createHmac, timingSafeEqual, type Hmac } from "node:crypto";
2
+ import { rootCertificates } from "node:tls";
3
+ import { types } from "node:util";
4
+ import type { Settings } from "@opengeni/config";
5
+ import { ModalNativePreparationDeclarationV2 } from "@opengeni/contracts/modal-native-proof-v2";
6
+
7
+ // PRIVATE, unused configuration groundwork, not a host authorizer, capture
8
+ // receipt, original grant, native context or effect permit. The canonical host
9
+ // must authenticate and join live original authority before committing this
10
+ // draft into protected storage, and before using its matched snapshot for I/O.
11
+ // Never project its equality bytes into logs, status, errors or workflow history.
12
+ const SUBKEY_DOMAIN = "opengeni:modal-native:configuration-equality:subkey:v2";
13
+ const MESSAGE_DOMAIN = "opengeni:modal-native:configuration-equality:framed:v2\0";
14
+ const MAX_DECLARATION_BYTES = 4 * 1024 * 1024;
15
+ const SERVER_URL = "https://api.modal.com:443";
16
+ const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);
17
+ const nativeByteLength = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteLength")!.get!;
18
+ const nativeByteOffset = Object.getOwnPropertyDescriptor(typedArrayPrototype, "byteOffset")!.get!;
19
+ const nativeBuffer = Object.getOwnPropertyDescriptor(typedArrayPrototype, "buffer")!.get!;
20
+ type ConfigurationSettings = Pick<
21
+ Settings,
22
+ "modalTokenId" | "modalTokenSecret" | "modalEnvironment" | "environmentsEncryptionKey"
23
+ >;
24
+
25
+ export type NativeOriginalConfigurationSnapshot = Readonly<{
26
+ serverUrl: string;
27
+ tokenId: string;
28
+ tokenSecret: string;
29
+ environment: string;
30
+ }>;
31
+
32
+ function readProfile(environment: string) {
33
+ return Object.freeze({
34
+ protocol: "modal-direct-original-read-grpc-v1" as const,
35
+ version: 1 as const,
36
+ sourceGitBlob: "7599f5b80cf111a25f78f427cfb2616d7e24b36c" as const,
37
+ serverUrl: SERVER_URL,
38
+ serverSelection: "host-pinned-modal-0.9-default" as const,
39
+ credentialSelection: "explicit-deployment-settings-pair-only" as const,
40
+ environmentSelection: "explicit-own-settings-no-default" as const,
41
+ environment,
42
+ environmentTransmittedByCpReads: false as const,
43
+ namespaceSelection: "unbound-until-authenticated-once-capture" as const,
44
+ modalProjectionVersion: "0.9.0" as const,
45
+ grpcJsVersion: "1.14.4" as const,
46
+ protobufJsVersion: "7.6.5" as const,
47
+ rpcPrefix: "/modal.client.ModalClient/" as const,
48
+ methods: ["AuthTokenGet", "WorkspaceNameLookup", "TaskGetCommandRouterAccess"] as const,
49
+ authHeaders: {
50
+ clientType: "8",
51
+ clientVersion: "1.0.0",
52
+ libmodalVersion: "modal-js/0.9.0",
53
+ } as const,
54
+ tlsPolicy: "explicit-node-tls-rootCertificates-v1" as const,
55
+ tlsRootsSha256: createHash("sha256").update(rootCertificates.join("\n")).digest("hex"),
56
+ retries: 0 as const,
57
+ nativeChainDeadlineMs: 30_000 as const,
58
+ maxWireBytes: 1_048_576 as const,
59
+ });
60
+ }
61
+
62
+ type PrivateDescription = Readonly<{
63
+ protocol: "opengeni-modal-native-configuration-equality";
64
+ version: 2;
65
+ purpose: "original-native-custody-proof";
66
+ configurationCaptureRef: ModalNativePreparationDeclarationV2["configurationCaptureRef"];
67
+ proofGrantRef: ModalNativePreparationDeclarationV2["proofGrantRef"];
68
+ declarationJson: string;
69
+ declarationSha256: string;
70
+ profile: ReturnType<typeof readProfile>;
71
+ keySelection: "existing-environments-encryption-root-current-only";
72
+ algorithm: "hmac-sha256";
73
+ subkeyDomain: typeof SUBKEY_DOMAIN;
74
+ messageDomain: typeof MESSAGE_DOMAIN;
75
+ }>;
76
+
77
+ /** Sensitive PRIVATE storage draft, not proof that any row or grant committed. */
78
+ export type NativeOriginalConfigurationDraftV2 = Readonly<{
79
+ description: PrivateDescription;
80
+ equality: Uint8Array;
81
+ }>;
82
+
83
+ declare const sampleBrand: unique symbol;
84
+ export type NativeOriginalConfigurationSample = Readonly<{ [sampleBrand]: true }>;
85
+ type SampleState = {
86
+ snapshot: NativeOriginalConfigurationSnapshot;
87
+ description: PrivateDescription;
88
+ declarationBytes: Buffer;
89
+ equality: Buffer;
90
+ };
91
+ const samples = new WeakMap<NativeOriginalConfigurationSample, SampleState>();
92
+
93
+ function settingsStrings(input: ConfigurationSettings): Record<string, string> | null {
94
+ if (!input || typeof input !== "object" || types.isProxy(input)) return null;
95
+ const prototype = Object.getPrototypeOf(input);
96
+ if (prototype !== Object.prototype && prototype !== null) return null;
97
+ const result: Record<string, string> = {};
98
+ for (const key of [
99
+ "modalTokenId",
100
+ "modalTokenSecret",
101
+ "modalEnvironment",
102
+ "environmentsEncryptionKey",
103
+ ]) {
104
+ const property = Object.getOwnPropertyDescriptor(input, key);
105
+ if (!property || !("value" in property) || typeof property.value !== "string") return null;
106
+ result[key] = property.value;
107
+ }
108
+ if (
109
+ !/^[\x20-\x7e]{1,8192}$/.test(result.modalTokenId!) ||
110
+ !/^[\x20-\x7e]{1,8192}$/.test(result.modalTokenSecret!) ||
111
+ result.modalEnvironment!.length > 200 ||
112
+ !/^[A-Za-z0-9+/]{43}=$/.test(result.environmentsEncryptionKey!)
113
+ )
114
+ return null;
115
+ return result;
116
+ }
117
+
118
+ function copyDeclaration(input: Uint8Array): Buffer | null {
119
+ if (!input || types.isProxy(input) || !types.isUint8Array(input)) return null;
120
+ try {
121
+ const byteLength = nativeByteLength.call(input) as number;
122
+ const byteOffset = nativeByteOffset.call(input) as number;
123
+ const buffer = nativeBuffer.call(input) as ArrayBuffer;
124
+ if (byteLength === 0 || byteLength > MAX_DECLARATION_BYTES || types.isSharedArrayBuffer(buffer))
125
+ return null;
126
+ return Buffer.from(new Uint8Array(buffer, byteOffset, byteLength));
127
+ } catch {
128
+ return null;
129
+ }
130
+ }
131
+
132
+ function frame(hmac: Hmac, label: string, bytes: Buffer) {
133
+ const length = Buffer.alloc(4);
134
+ length.writeUInt32BE(bytes.length);
135
+ hmac.update(label).update("\0").update(length).update(bytes);
136
+ }
137
+
138
+ /** Samples ONLY explicit own settings, without environment/profile/SDK lookup.
139
+ * A parsed declaration merely supplies correlation. Genuine known app/image
140
+ * provenance and same-transaction host/grant/admission checks remain external.
141
+ */
142
+ export function sampleNativeOriginalConfiguration(
143
+ settings: ConfigurationSettings,
144
+ declarationBytes: Uint8Array,
145
+ ): NativeOriginalConfigurationSample | null {
146
+ const selected = settingsStrings(settings);
147
+ const body = copyDeclaration(declarationBytes);
148
+ if (!selected || !body) {
149
+ body?.fill(0);
150
+ return null;
151
+ }
152
+ let root: Buffer | undefined;
153
+ let subkey: Buffer | undefined;
154
+ let tokenId: Buffer | undefined;
155
+ let tokenSecret: Buffer | undefined;
156
+ let profileBytes: Buffer | undefined;
157
+ let retained = false;
158
+ try {
159
+ const json = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(body);
160
+ const declaration = ModalNativePreparationDeclarationV2.parse(JSON.parse(json));
161
+ root = Buffer.from(selected.environmentsEncryptionKey!, "base64");
162
+ if (root.length !== 32 || root.toString("base64") !== selected.environmentsEncryptionKey)
163
+ return null;
164
+ const snapshot = Object.freeze({
165
+ serverUrl: SERVER_URL,
166
+ tokenId: selected.modalTokenId!,
167
+ tokenSecret: selected.modalTokenSecret!,
168
+ environment: selected.modalEnvironment!,
169
+ });
170
+ const description: PrivateDescription = Object.freeze({
171
+ protocol: "opengeni-modal-native-configuration-equality",
172
+ version: 2,
173
+ purpose: "original-native-custody-proof",
174
+ configurationCaptureRef: declaration.configurationCaptureRef,
175
+ proofGrantRef: declaration.proofGrantRef,
176
+ declarationJson: json,
177
+ declarationSha256: createHash("sha256").update(body).digest("hex"),
178
+ profile: readProfile(snapshot.environment),
179
+ keySelection: "existing-environments-encryption-root-current-only",
180
+ algorithm: "hmac-sha256",
181
+ subkeyDomain: SUBKEY_DOMAIN,
182
+ messageDomain: MESSAGE_DOMAIN,
183
+ });
184
+ subkey = createHmac("sha256", root).update(SUBKEY_DOMAIN).digest();
185
+ tokenId = Buffer.from(snapshot.tokenId, "utf8");
186
+ tokenSecret = Buffer.from(snapshot.tokenSecret, "utf8");
187
+ profileBytes = Buffer.from(JSON.stringify(description), "utf8");
188
+ const hmac = createHmac("sha256", subkey).update(MESSAGE_DOMAIN);
189
+ frame(hmac, "original-declaration", body);
190
+ frame(hmac, "private-configuration", profileBytes);
191
+ frame(hmac, "exact-token-id", tokenId);
192
+ frame(hmac, "exact-token-secret", tokenSecret);
193
+ const sample = Object.freeze({}) as NativeOriginalConfigurationSample;
194
+ samples.set(sample, { snapshot, description, declarationBytes: body, equality: hmac.digest() });
195
+ retained = true;
196
+ return sample;
197
+ } catch {
198
+ // Fixed refusal, never validator details, credentials or keyed material.
199
+ return null;
200
+ } finally {
201
+ root?.fill(0);
202
+ subkey?.fill(0);
203
+ tokenId?.fill(0);
204
+ tokenSecret?.fill(0);
205
+ profileBytes?.fill(0);
206
+ if (!retained) body.fill(0);
207
+ }
208
+ }
209
+
210
+ /** Private draft extraction for protected storage only; never a status DTO. */
211
+ export function privateNativeOriginalConfigurationDraft(
212
+ sample: NativeOriginalConfigurationSample,
213
+ ): NativeOriginalConfigurationDraftV2 | null {
214
+ const state = samples.get(sample);
215
+ return state
216
+ ? { description: structuredClone(state.description), equality: Uint8Array.from(state.equality) }
217
+ : null;
218
+ }
219
+
220
+ /** Same sampled strings for a future authenticated native caller; NOT a grant. */
221
+ export function nativeOriginalConfigurationSnapshot(
222
+ sample: NativeOriginalConfigurationSample,
223
+ ): NativeOriginalConfigurationSnapshot | null {
224
+ return samples.get(sample)?.snapshot ?? null;
225
+ }
226
+
227
+ /** PRIVATE equality check only. No public oracle, grant renewal or key fallback.
228
+ * Restart reconstruction still requires an authenticated protected original row.
229
+ */
230
+ export function currentNativeOriginalConfigurationMatches(
231
+ sample: NativeOriginalConfigurationSample,
232
+ settings: ConfigurationSettings,
233
+ ): boolean {
234
+ const state = samples.get(sample);
235
+ if (!state) return false;
236
+ const current = sampleNativeOriginalConfiguration(settings, state.declarationBytes);
237
+ if (!current) return false;
238
+ try {
239
+ const candidate = samples.get(current)!;
240
+ return (
241
+ state.equality.length === 32 &&
242
+ candidate.equality.length === 32 &&
243
+ timingSafeEqual(state.equality, candidate.equality)
244
+ );
245
+ } finally {
246
+ disposeNativeOriginalConfigurationSample(current);
247
+ }
248
+ }
249
+
250
+ /** Wipes owned mutable copies, not JS immutable strings or native I/O/custody.
251
+ * A future owning native caller must join its real callbacks separately.
252
+ */
253
+ export function disposeNativeOriginalConfigurationSample(
254
+ sample: NativeOriginalConfigurationSample,
255
+ ) {
256
+ const state = samples.get(sample);
257
+ if (!state) return;
258
+ state.declarationBytes.fill(0);
259
+ state.equality.fill(0);
260
+ samples.delete(sample);
261
+ }