@opengeni/interaction 0.4.3 → 0.4.12-canary.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/controller-core.d.ts +8 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/controller-core.ts +24 -0
- package/src/index.ts +2 -0
|
@@ -12,6 +12,14 @@ export declare class InteractionDefiniteDriverError extends Error {
|
|
|
12
12
|
readonly retryable: boolean;
|
|
13
13
|
constructor(code: InteractionError["code"], message: string, retryable?: boolean);
|
|
14
14
|
}
|
|
15
|
+
/** Driver proof that dispatch occurred but the exact native outcome could not
|
|
16
|
+
* be confirmed. Unlike an arbitrary transport exception, this preserves the
|
|
17
|
+
* adapter's bounded, user-actionable diagnosis without pretending certainty. */
|
|
18
|
+
export declare class InteractionOutcomeUnknownDriverError extends Error {
|
|
19
|
+
readonly code: InteractionError["code"];
|
|
20
|
+
readonly retryable: boolean;
|
|
21
|
+
constructor(code: InteractionError["code"], message: string, retryable?: boolean);
|
|
22
|
+
}
|
|
15
23
|
export type InteractionCoreCommand = {
|
|
16
24
|
operationId: string;
|
|
17
25
|
controllerGeneration: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type BrowserActionCommand as BrowserActionCommandValue, type BrowserActionReceipt as BrowserActionReceiptValue, type BrowserObservation as BrowserObservationValue, type BrowserProtectedAuthFillCommand as BrowserProtectedAuthFillCommandValue, type BrowserProtectedAuthFillReceipt as BrowserProtectedAuthFillReceiptValue, type BrowserProtectedAuthObservation as BrowserProtectedAuthObservationValue, type BrowserTarget as BrowserTargetValue, type ComputerActionCommand as ComputerActionCommandValue, type ComputerActionReceipt as ComputerActionReceiptValue, type ComputerObservation as ComputerObservationValue, type ComputerTarget as ComputerTargetValue } from "@opengeni/contracts";
|
|
2
|
-
import { InteractionControllerError, InteractionDefiniteDriverError, type InteractionControllerErrorCode, type InteractionOperationJournalRecord } from "./controller-core.js";
|
|
3
|
-
export { InteractionControllerError, InteractionDefiniteDriverError, type InteractionControllerErrorCode, };
|
|
2
|
+
import { InteractionControllerError, InteractionDefiniteDriverError, InteractionOutcomeUnknownDriverError, type InteractionControllerErrorCode, type InteractionOperationJournalRecord } from "./controller-core.js";
|
|
3
|
+
export { InteractionControllerError, InteractionDefiniteDriverError, InteractionOutcomeUnknownDriverError, type InteractionControllerErrorCode, };
|
|
4
4
|
export type BrowserInteractionDriver = {
|
|
5
5
|
target(targetId: string): Promise<BrowserTargetValue | null>;
|
|
6
6
|
observe(targetId: string): Promise<BrowserObservationValue>;
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,14 @@ var InteractionDefiniteDriverError = class extends Error {
|
|
|
32
32
|
this.name = "InteractionDefiniteDriverError";
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
|
+
var InteractionOutcomeUnknownDriverError = class extends Error {
|
|
36
|
+
constructor(code, message, retryable = false) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.code = code;
|
|
39
|
+
this.retryable = retryable;
|
|
40
|
+
this.name = "InteractionOutcomeUnknownDriverError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
35
43
|
var terminalStates = /* @__PURE__ */ new Set([
|
|
36
44
|
"completed",
|
|
37
45
|
"failed",
|
|
@@ -199,6 +207,16 @@ var InteractionControllerCore = class {
|
|
|
199
207
|
})
|
|
200
208
|
);
|
|
201
209
|
}
|
|
210
|
+
if (error instanceof InteractionOutcomeUnknownDriverError) {
|
|
211
|
+
return await this.settle(
|
|
212
|
+
entry,
|
|
213
|
+
this.makeReceipt(command, "outcome_unknown", dispatchedAt, this.timestamp(), null, {
|
|
214
|
+
code: error.code,
|
|
215
|
+
message: error.message,
|
|
216
|
+
retryable: error.retryable
|
|
217
|
+
})
|
|
218
|
+
);
|
|
219
|
+
}
|
|
202
220
|
return await this.settle(
|
|
203
221
|
entry,
|
|
204
222
|
this.makeReceipt(command, "outcome_unknown", dispatchedAt, this.timestamp(), null, {
|
|
@@ -718,6 +736,7 @@ export {
|
|
|
718
736
|
ComputerInteractionController,
|
|
719
737
|
InteractionControllerError,
|
|
720
738
|
InteractionDefiniteDriverError,
|
|
739
|
+
InteractionOutcomeUnknownDriverError,
|
|
721
740
|
recoverBrowserOperationJournalRecord,
|
|
722
741
|
recoverBrowserProtectedAuthOperationJournalRecord,
|
|
723
742
|
recoverComputerOperationJournalRecord
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/controller-core.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n BrowserActionCommand,\n BrowserActionReceipt,\n BrowserObservation,\n BrowserProtectedAuthFillCommand,\n BrowserProtectedAuthFillReceipt,\n BrowserProtectedAuthObservation,\n BrowserTarget,\n ComputerActionCommand,\n ComputerActionReceipt,\n ComputerObservation,\n ComputerTarget,\n type BrowserActionCommand as BrowserActionCommandValue,\n type BrowserActionReceipt as BrowserActionReceiptValue,\n type BrowserObservation as BrowserObservationValue,\n type BrowserProtectedAuthFillCommand as BrowserProtectedAuthFillCommandValue,\n type BrowserProtectedAuthFillReceipt as BrowserProtectedAuthFillReceiptValue,\n type BrowserProtectedAuthObservation as BrowserProtectedAuthObservationValue,\n type BrowserTarget as BrowserTargetValue,\n type ComputerActionCommand as ComputerActionCommandValue,\n type ComputerActionReceipt as ComputerActionReceiptValue,\n type ComputerObservation as ComputerObservationValue,\n type ComputerTarget as ComputerTargetValue,\n} from \"@opengeni/contracts\";\nimport {\n InteractionControllerCore,\n InteractionControllerError,\n InteractionDefiniteDriverError,\n recoverInteractionReceipt,\n type InteractionControllerErrorCode,\n type InteractionOperationJournalRecord,\n} from \"./controller-core\";\n\nexport {\n InteractionControllerError,\n InteractionDefiniteDriverError,\n type InteractionControllerErrorCode,\n};\n\nexport type BrowserInteractionDriver = {\n target(targetId: string): Promise<BrowserTargetValue | null>;\n observe(targetId: string): Promise<BrowserObservationValue>;\n validate?(command: BrowserActionCommandValue, target: BrowserTargetValue): Promise<void> | void;\n dispatch(command: BrowserActionCommandValue): Promise<BrowserObservationValue | null>;\n};\n\nexport type BrowserInteractionAuthority = {\n authorizeDispatch(command: BrowserActionCommandValue): Promise<void> | void;\n};\n\nexport type BrowserOperationJournalRecord =\n InteractionOperationJournalRecord<BrowserActionReceiptValue>;\n\nexport type BrowserInteractionControllerOptions = {\n browserSessionId: string;\n controllerGeneration: string;\n driver: BrowserInteractionDriver;\n authority?: BrowserInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly BrowserOperationJournalRecord[];\n onJournalRecord?: (record: BrowserOperationJournalRecord) => Promise<void> | void;\n};\n\n/** Placement-resident BrowserSession mutation authority. */\nexport class BrowserInteractionController {\n private readonly core: InteractionControllerCore<\n BrowserActionCommandValue,\n BrowserTargetValue,\n BrowserObservationValue,\n BrowserActionReceiptValue\n >;\n\n constructor(options: BrowserInteractionControllerOptions) {\n const { browserSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n adapter: {\n resourceLabel: \"browser\",\n parseCommand: (value) => BrowserActionCommand.parse(value),\n parseTarget: (value) => BrowserTarget.parse(value),\n parseObservation: (value) => BrowserObservation.parse(value),\n parseReceipt: (value) => BrowserActionReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.browserSessionId !== browserSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"browser command targets another browser session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.browserSessionId !== browserSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"browser target changed before the command could dispatch\",\n true,\n );\n }\n if (command.expectedDocumentGeneration !== target.documentGeneration) {\n throw new InteractionControllerError(\n \"document_stale\",\n \"browser document changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.browserSessionId !== browserSessionId ||\n observation.target.id !== targetId ||\n observation.target.browserSessionId !== browserSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"browser driver returned an observation outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return BrowserActionReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n browserSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.browserSessionId !== browserSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n );\n },\n },\n });\n }\n\n observe(targetId: string): Promise<BrowserObservationValue> {\n return this.core.observe(targetId);\n }\n\n run(command: BrowserActionCommandValue): Promise<BrowserActionReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): BrowserActionReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): BrowserOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverBrowserOperationJournalRecord(\n record: BrowserOperationJournalRecord,\n settledAt: string,\n): BrowserOperationJournalRecord {\n const receipt = BrowserActionReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n ),\n };\n}\n\nexport type BrowserProtectedAuthDriver = {\n target(targetId: string): Promise<BrowserTargetValue | null>;\n observe(targetId: string): Promise<BrowserProtectedAuthObservationValue>;\n validate?(\n command: BrowserProtectedAuthFillCommandValue,\n target: BrowserTargetValue,\n ): Promise<void> | void;\n dispatch(\n command: BrowserProtectedAuthFillCommandValue,\n ): Promise<BrowserProtectedAuthObservationValue>;\n};\n\nexport type BrowserProtectedAuthAuthority = {\n authorizeDispatch(command: BrowserProtectedAuthFillCommandValue): Promise<void> | void;\n};\n\nexport type BrowserProtectedAuthOperationJournalRecord =\n InteractionOperationJournalRecord<BrowserProtectedAuthFillReceiptValue>;\n\nexport type BrowserProtectedAuthControllerOptions = {\n browserSessionId: string;\n controllerGeneration: string;\n driver: BrowserProtectedAuthDriver;\n authority?: BrowserProtectedAuthAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly BrowserProtectedAuthOperationJournalRecord[];\n onJournalRecord?: (record: BrowserProtectedAuthOperationJournalRecord) => Promise<void> | void;\n};\n\n/** Secret-bearing commands are admitted only through this controller-private\n * authority. Its durable digest binds all semantics plus credential version,\n * but deliberately excludes ephemeral password/TOTP value bytes. */\nexport class BrowserProtectedAuthController {\n private readonly core: InteractionControllerCore<\n BrowserProtectedAuthFillCommandValue,\n BrowserTargetValue,\n BrowserProtectedAuthObservationValue,\n BrowserProtectedAuthFillReceiptValue\n >;\n\n constructor(options: BrowserProtectedAuthControllerOptions) {\n const { browserSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n commandDigest: protectedAuthCommandDigest,\n adapter: {\n resourceLabel: \"browser protected fill\",\n parseCommand: (value) => BrowserProtectedAuthFillCommand.parse(value),\n parseTarget: (value) => BrowserTarget.parse(value),\n parseObservation: (value) => BrowserProtectedAuthObservation.parse(value),\n parseReceipt: (value) => BrowserProtectedAuthFillReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.browserSessionId !== browserSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"protected fill targets another browser session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"protected fill targets a stale browser controller\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.browserSessionId !== browserSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"protected-fill target belongs to a stale browser controller\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"browser target changed before protected fill\",\n true,\n );\n }\n if (command.expectedDocumentGeneration !== target.documentGeneration) {\n throw new InteractionControllerError(\n \"document_stale\",\n \"browser document changed before protected fill\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.target.id !== targetId ||\n observation.target.browserSessionId !== browserSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"protected-fill driver returned a result outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return BrowserProtectedAuthFillReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n browserSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.browserSessionId !== browserSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored protected-fill operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"browser protected fill\", (value) =>\n BrowserProtectedAuthFillReceipt.parse(value),\n );\n },\n },\n });\n }\n\n run(\n command: BrowserProtectedAuthFillCommandValue,\n ): Promise<BrowserProtectedAuthFillReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): BrowserProtectedAuthFillReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): BrowserProtectedAuthOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverBrowserProtectedAuthOperationJournalRecord(\n record: BrowserProtectedAuthOperationJournalRecord,\n settledAt: string,\n): BrowserProtectedAuthOperationJournalRecord {\n const receipt = BrowserProtectedAuthFillReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"browser protected fill\", (value) =>\n BrowserProtectedAuthFillReceipt.parse(value),\n ),\n };\n}\n\nfunction protectedAuthCommandDigest(command: BrowserProtectedAuthFillCommandValue): string {\n const { fields, ...metadata } = command;\n const secretFree = {\n ...metadata,\n fields: fields.map(({ value: _value, ...field }) => field),\n };\n return createHash(\"sha256\").update(canonicalJson(secretFree), \"utf8\").digest(\"hex\");\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport type ComputerInteractionDriver = {\n target(targetId: string): Promise<ComputerTargetValue | null>;\n observe(targetId: string): Promise<ComputerObservationValue>;\n validate?(command: ComputerActionCommandValue, target: ComputerTargetValue): Promise<void> | void;\n dispatch(command: ComputerActionCommandValue): Promise<ComputerObservationValue | null>;\n};\n\nexport type ComputerInteractionAuthority = {\n authorizeDispatch(command: ComputerActionCommandValue): Promise<void> | void;\n};\n\nexport type ComputerOperationJournalRecord =\n InteractionOperationJournalRecord<ComputerActionReceiptValue>;\n\nexport type ComputerInteractionControllerOptions = {\n computerSessionId: string;\n controllerGeneration: string;\n driver: ComputerInteractionDriver;\n authority?: ComputerInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly ComputerOperationJournalRecord[];\n onJournalRecord?: (record: ComputerOperationJournalRecord) => Promise<void> | void;\n};\n\n/** Placement-resident ComputerSession mutation authority. Linux AT-SPI/X11,\n * macOS AX/ScreenCaptureKit, and later UIA adapters share this exact core. */\nexport class ComputerInteractionController {\n private readonly core: InteractionControllerCore<\n ComputerActionCommandValue,\n ComputerTargetValue,\n ComputerObservationValue,\n ComputerActionReceiptValue\n >;\n\n constructor(options: ComputerInteractionControllerOptions) {\n const { computerSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n adapter: {\n resourceLabel: \"computer\",\n parseCommand: (value) => ComputerActionCommand.parse(value),\n parseTarget: (value) => ComputerTarget.parse(value),\n parseObservation: (value) => ComputerObservation.parse(value),\n parseReceipt: (value) => ComputerActionReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.computerSessionId !== computerSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"computer command targets another computer session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.computerSessionId !== computerSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"computer target changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.computerSessionId !== computerSessionId ||\n observation.target.id !== targetId ||\n observation.target.computerSessionId !== computerSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"computer driver returned an observation outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return ComputerActionReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n computerSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.computerSessionId !== computerSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerActionReceipt.parse(value),\n );\n },\n },\n });\n }\n\n observe(targetId: string): Promise<ComputerObservationValue> {\n return this.core.observe(targetId);\n }\n\n run(command: ComputerActionCommandValue): Promise<ComputerActionReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): ComputerActionReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): ComputerOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverComputerOperationJournalRecord(\n record: ComputerOperationJournalRecord,\n settledAt: string,\n): ComputerOperationJournalRecord {\n const receipt = ComputerActionReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerActionReceipt.parse(value),\n ),\n };\n}\n","import { createHash } from \"node:crypto\";\nimport type { InteractionError, InteractionOperationState } from \"@opengeni/contracts\";\n\nexport type InteractionControllerErrorCode = InteractionError[\"code\"] | \"journal_full\";\n\n/** A safe, typed rejection known not to have dispatched a side effect. */\nexport class InteractionControllerError extends Error {\n constructor(\n readonly code: InteractionControllerErrorCode,\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionControllerError\";\n }\n}\n\n/** Driver proof that a dispatched command definitively failed without an ambiguous outcome. */\nexport class InteractionDefiniteDriverError extends Error {\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionDefiniteDriverError\";\n }\n}\n\nexport type InteractionCoreCommand = {\n operationId: string;\n controllerGeneration: string;\n targetId: string;\n};\n\nexport type InteractionCoreTarget = {\n id: string;\n controllerGeneration: string;\n};\n\nexport type InteractionCoreObservation<TTarget extends InteractionCoreTarget> = {\n target: TTarget;\n};\n\nexport type InteractionCoreReceipt<TObservation> = {\n operationId: string;\n controllerGeneration: string;\n targetId: string;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n};\n\nexport type InteractionOperationJournalRecord<TReceipt> = {\n operationId: string;\n commandDigest: string;\n receipt: TReceipt;\n};\n\ntype InteractionDriver<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n> = {\n target(targetId: string): Promise<TTarget | null>;\n observe(targetId: string): Promise<TObservation>;\n validate?(command: TCommand, target: TTarget): Promise<void> | void;\n dispatch(command: TCommand): Promise<TObservation | null>;\n};\n\ntype InteractionCoreAdapter<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n resourceLabel: string;\n parseCommand(value: unknown): TCommand;\n parseTarget(value: unknown): TTarget;\n parseObservation(value: unknown): TObservation;\n parseReceipt(value: unknown): TReceipt;\n assertCommandAuthority(command: TCommand): void;\n assertTargetAuthority(target: TTarget): void;\n assertExpectedGenerations(command: TCommand, target: TTarget): void;\n assertObservationAuthority(observation: TObservation, targetId: string): void;\n makeReceipt(input: {\n command: TCommand;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n }): TReceipt;\n recoverReceipt(receipt: TReceipt, settledAt: string): TReceipt;\n};\n\ntype InteractionCoreAuthority<TCommand> = {\n authorizeDispatch(command: TCommand): Promise<void> | void;\n};\n\nexport type InteractionControllerCoreOptions<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n driver: InteractionDriver<TCommand, TTarget, TObservation>;\n adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n authority?: InteractionCoreAuthority<TCommand>;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly InteractionOperationJournalRecord<TReceipt>[];\n onJournalRecord?: (record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void;\n /** Override only when a private command contains ephemeral secret material.\n * The callback must bind every non-secret semantic input while excluding the\n * value bytes themselves and return lowercase SHA-256. */\n commandDigest?: (command: TCommand) => string;\n};\n\ntype JournalEntry<TReceipt> = InteractionOperationJournalRecord<TReceipt> & {\n completion: Promise<TReceipt>;\n preparationPersisted: Promise<boolean>;\n};\n\nconst terminalStates = new Set<InteractionOperationState>([\n \"completed\",\n \"failed\",\n \"outcome_unknown\",\n]);\n\n/**\n * Resource-neutral placement mutation authority. Public Browser and Computer\n * controllers supply only their schemas and generation semantics; journaling,\n * idempotency, target-local serialization, and crash policy stay identical.\n */\nexport class InteractionControllerCore<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> {\n private readonly driver: InteractionDriver<TCommand, TTarget, TObservation>;\n private readonly adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n private readonly authority: InteractionCoreAuthority<TCommand> | undefined;\n private readonly maxJournalEntries: number;\n private readonly now: () => Date;\n private readonly onJournalRecord:\n | ((record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void)\n | undefined;\n private readonly commandDigest: (command: TCommand) => string;\n private readonly journal = new Map<string, JournalEntry<TReceipt>>();\n private readonly targetTails = new Map<string, Promise<void>>();\n\n constructor(\n options: InteractionControllerCoreOptions<TCommand, TTarget, TObservation, TReceipt>,\n ) {\n this.driver = options.driver;\n this.adapter = options.adapter;\n this.authority = options.authority;\n this.maxJournalEntries = options.maxJournalEntries ?? 10_000;\n this.now = options.now ?? (() => new Date());\n this.onJournalRecord = options.onJournalRecord;\n this.commandDigest = options.commandDigest ?? digestJson;\n if (!Number.isSafeInteger(this.maxJournalEntries) || this.maxJournalEntries < 1) {\n throw new Error(\"maxJournalEntries must be a positive safe integer\");\n }\n for (const record of options.initialJournal ?? []) this.restoreJournalRecord(record);\n }\n\n async observe(targetId: string): Promise<TObservation> {\n const target = await this.requireCurrentTarget(targetId);\n const observed = this.adapter.parseObservation(await this.driver.observe(target.id));\n this.adapter.assertObservationAuthority(observed, target.id);\n return observed;\n }\n\n run(commandInput: TCommand): Promise<TReceipt> {\n const command = this.adapter.parseCommand(commandInput);\n this.adapter.assertCommandAuthority(command);\n const commandDigest = this.commandDigest(command);\n if (!/^[0-9a-f]{64}$/u.test(commandDigest)) {\n throw new Error(`${this.adapter.resourceLabel} command digest must be lowercase SHA-256`);\n }\n const existing = this.journal.get(command.operationId);\n if (existing) {\n if (existing.commandDigest !== commandDigest) {\n throw new InteractionControllerError(\n \"operation_conflict\",\n `operation id is already bound to a different ${this.adapter.resourceLabel} command`,\n );\n }\n return existing.completion;\n }\n\n this.makeJournalSpace();\n const prepared = this.makeReceipt(command, \"prepared\", null, null, null, null);\n const entry: JournalEntry<TReceipt> = {\n operationId: command.operationId,\n commandDigest,\n receipt: prepared,\n completion: Promise.resolve(prepared),\n preparationPersisted: this.publish(command.operationId, commandDigest, prepared).then(\n () => true,\n () => false,\n ),\n };\n this.journal.set(command.operationId, entry);\n\n const previous = this.targetTails.get(command.targetId) ?? Promise.resolve();\n entry.completion = previous.then(async () => await this.execute(entry, command));\n const tail = entry.completion.then(\n () => undefined,\n () => undefined,\n );\n this.targetTails.set(command.targetId, tail);\n void tail.finally(() => {\n if (this.targetTails.get(command.targetId) === tail)\n this.targetTails.delete(command.targetId);\n });\n return entry.completion;\n }\n\n receipt(operationId: string): TReceipt | null {\n return this.journal.get(operationId)?.receipt ?? null;\n }\n\n journalSnapshot(): InteractionOperationJournalRecord<TReceipt>[] {\n return [...this.journal.values()].map(({ operationId, commandDigest, receipt }) => ({\n operationId,\n commandDigest,\n receipt,\n }));\n }\n\n /** Wait until every command already admitted to a target queue settles.\n * Callers must fence new dispatch through `authority` before awaiting this. */\n async waitForIdle(): Promise<void> {\n while (this.targetTails.size > 0) await Promise.all([...this.targetTails.values()]);\n }\n\n private async execute(entry: JournalEntry<TReceipt>, command: TCommand): Promise<TReceipt> {\n if (!(await entry.preparationPersisted)) {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal rejected the command before dispatch`,\n );\n }\n\n try {\n await this.authority?.authorizeDispatch(command);\n const target = await this.requireCurrentTarget(command.targetId);\n this.adapter.assertExpectedGenerations(command, target);\n await this.driver.validate?.(command, target);\n } catch (error) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"failed\",\n null,\n this.timestamp(),\n null,\n safePredispatchError(error, this.adapter.resourceLabel),\n ),\n );\n }\n\n const dispatchedAt = this.timestamp();\n const dispatched = this.makeReceipt(command, \"dispatched\", dispatchedAt, null, null, null);\n try {\n await this.publish(entry.operationId, entry.commandDigest, dispatched);\n entry.receipt = dispatched;\n } catch {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal became unavailable before dispatch`,\n );\n }\n\n try {\n const dispatchedObservation = await this.driver.dispatch(command);\n const observation =\n dispatchedObservation === null\n ? null\n : this.adapter.parseObservation(dispatchedObservation);\n if (observation) this.adapter.assertObservationAuthority(observation, command.targetId);\n const completed = this.makeReceipt(\n command,\n \"completed\",\n dispatchedAt,\n this.timestamp(),\n observation,\n null,\n );\n try {\n await this.publish(entry.operationId, entry.commandDigest, completed);\n entry.receipt = completed;\n return completed;\n } catch {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command completed but its durable outcome could not be recorded`,\n retryable: false,\n }),\n );\n }\n } catch (error) {\n if (error instanceof InteractionDefiniteDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"failed\", dispatchedAt, this.timestamp(), null, {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n }),\n );\n }\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command outcome is unknown after dispatch`,\n retryable: false,\n }),\n );\n }\n }\n\n private async requireCurrentTarget(targetId: string): Promise<TTarget> {\n const target = await this.driver.target(targetId);\n if (!target) {\n throw new InteractionControllerError(\n \"target_not_found\",\n `${this.adapter.resourceLabel} target does not exist`,\n );\n }\n const parsed = this.adapter.parseTarget(target);\n this.adapter.assertTargetAuthority(parsed);\n return parsed;\n }\n\n private makeReceipt(\n command: TCommand,\n state: InteractionOperationState,\n dispatchedAt: string | null,\n settledAt: string | null,\n observation: TObservation | null,\n error: InteractionError | null,\n ): TReceipt {\n return this.adapter.makeReceipt({\n command,\n state,\n dispatchedAt,\n settledAt,\n observation,\n error,\n });\n }\n\n private async settle(entry: JournalEntry<TReceipt>, receipt: TReceipt): Promise<TReceipt> {\n entry.receipt = receipt;\n try {\n await this.publish(entry.operationId, entry.commandDigest, receipt);\n } catch {\n // Controller-lifetime terminal truth remains authoritative. A restored\n // dispatched receipt is always recovered as outcome_unknown, never replayed.\n }\n return receipt;\n }\n\n private async failBeforeDispatch(\n entry: JournalEntry<TReceipt>,\n command: TCommand,\n message: string,\n ): Promise<TReceipt> {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"failed\", null, this.timestamp(), null, {\n code: \"driver_failed\",\n message,\n retryable: true,\n }),\n );\n }\n\n private async publish(\n operationId: string,\n commandDigest: string,\n receipt: TReceipt,\n ): Promise<void> {\n await this.onJournalRecord?.({ operationId, commandDigest, receipt });\n }\n\n private timestamp(): string {\n return this.now().toISOString();\n }\n\n private makeJournalSpace(): void {\n while (this.journal.size >= this.maxJournalEntries) {\n const terminal = [...this.journal.entries()].find(([, entry]) =>\n terminalStates.has(entry.receipt.state),\n );\n if (!terminal) {\n throw new InteractionControllerError(\n \"journal_full\",\n `${this.adapter.resourceLabel} operation journal has no safely evictable terminal entry`,\n true,\n );\n }\n this.journal.delete(terminal[0]);\n }\n }\n\n private restoreJournalRecord(record: InteractionOperationJournalRecord<TReceipt>): void {\n if (this.journal.has(record.operationId)) {\n throw new Error(`duplicate restored operation id: ${record.operationId}`);\n }\n const parsed = this.adapter.parseReceipt(record.receipt);\n if (parsed.operationId !== record.operationId) {\n throw new Error(`restored operation ${record.operationId} has another receipt id`);\n }\n const receipt = this.adapter.recoverReceipt(parsed, this.timestamp());\n const entry: JournalEntry<TReceipt> = {\n operationId: record.operationId,\n commandDigest: record.commandDigest,\n receipt,\n completion: Promise.resolve(receipt),\n preparationPersisted: Promise.resolve(true),\n };\n this.journal.set(record.operationId, entry);\n }\n}\n\nexport function recoverInteractionReceipt<TReceipt extends InteractionCoreReceipt<unknown>>(\n receipt: TReceipt,\n settledAt: string,\n resourceLabel: string,\n parse: (value: unknown) => TReceipt,\n): TReceipt {\n if (terminalStates.has(receipt.state)) return receipt;\n return parse({\n ...receipt,\n state: receipt.state === \"dispatched\" ? \"outcome_unknown\" : \"failed\",\n settledAt,\n observation: null,\n error:\n receipt.state === \"dispatched\"\n ? {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted after command dispatch`,\n retryable: false,\n }\n : {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted before command dispatch`,\n retryable: true,\n },\n });\n}\n\nfunction safePredispatchError(error: unknown, resourceLabel: string): InteractionError {\n if (error instanceof InteractionControllerError && error.code !== \"journal_full\") {\n return {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n };\n }\n return {\n code: \"driver_failed\",\n message: `${resourceLabel} command failed before dispatch`,\n retryable: false,\n };\n}\n\nfunction digestJson(value: unknown): string {\n return createHash(\"sha256\").update(canonicalJson(value), \"utf8\").digest(\"hex\");\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n"],"mappings":"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","names":["createHash","createHash","canonicalJson","canonicalJsonValue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/controller-core.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport {\n BrowserActionCommand,\n BrowserActionReceipt,\n BrowserObservation,\n BrowserProtectedAuthFillCommand,\n BrowserProtectedAuthFillReceipt,\n BrowserProtectedAuthObservation,\n BrowserTarget,\n ComputerActionCommand,\n ComputerActionReceipt,\n ComputerObservation,\n ComputerTarget,\n type BrowserActionCommand as BrowserActionCommandValue,\n type BrowserActionReceipt as BrowserActionReceiptValue,\n type BrowserObservation as BrowserObservationValue,\n type BrowserProtectedAuthFillCommand as BrowserProtectedAuthFillCommandValue,\n type BrowserProtectedAuthFillReceipt as BrowserProtectedAuthFillReceiptValue,\n type BrowserProtectedAuthObservation as BrowserProtectedAuthObservationValue,\n type BrowserTarget as BrowserTargetValue,\n type ComputerActionCommand as ComputerActionCommandValue,\n type ComputerActionReceipt as ComputerActionReceiptValue,\n type ComputerObservation as ComputerObservationValue,\n type ComputerTarget as ComputerTargetValue,\n} from \"@opengeni/contracts\";\nimport {\n InteractionControllerCore,\n InteractionControllerError,\n InteractionDefiniteDriverError,\n InteractionOutcomeUnknownDriverError,\n recoverInteractionReceipt,\n type InteractionControllerErrorCode,\n type InteractionOperationJournalRecord,\n} from \"./controller-core\";\n\nexport {\n InteractionControllerError,\n InteractionDefiniteDriverError,\n InteractionOutcomeUnknownDriverError,\n type InteractionControllerErrorCode,\n};\n\nexport type BrowserInteractionDriver = {\n target(targetId: string): Promise<BrowserTargetValue | null>;\n observe(targetId: string): Promise<BrowserObservationValue>;\n validate?(command: BrowserActionCommandValue, target: BrowserTargetValue): Promise<void> | void;\n dispatch(command: BrowserActionCommandValue): Promise<BrowserObservationValue | null>;\n};\n\nexport type BrowserInteractionAuthority = {\n authorizeDispatch(command: BrowserActionCommandValue): Promise<void> | void;\n};\n\nexport type BrowserOperationJournalRecord =\n InteractionOperationJournalRecord<BrowserActionReceiptValue>;\n\nexport type BrowserInteractionControllerOptions = {\n browserSessionId: string;\n controllerGeneration: string;\n driver: BrowserInteractionDriver;\n authority?: BrowserInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly BrowserOperationJournalRecord[];\n onJournalRecord?: (record: BrowserOperationJournalRecord) => Promise<void> | void;\n};\n\n/** Placement-resident BrowserSession mutation authority. */\nexport class BrowserInteractionController {\n private readonly core: InteractionControllerCore<\n BrowserActionCommandValue,\n BrowserTargetValue,\n BrowserObservationValue,\n BrowserActionReceiptValue\n >;\n\n constructor(options: BrowserInteractionControllerOptions) {\n const { browserSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n adapter: {\n resourceLabel: \"browser\",\n parseCommand: (value) => BrowserActionCommand.parse(value),\n parseTarget: (value) => BrowserTarget.parse(value),\n parseObservation: (value) => BrowserObservation.parse(value),\n parseReceipt: (value) => BrowserActionReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.browserSessionId !== browserSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"browser command targets another browser session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.browserSessionId !== browserSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"browser target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"browser target changed before the command could dispatch\",\n true,\n );\n }\n if (command.expectedDocumentGeneration !== target.documentGeneration) {\n throw new InteractionControllerError(\n \"document_stale\",\n \"browser document changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.browserSessionId !== browserSessionId ||\n observation.target.id !== targetId ||\n observation.target.browserSessionId !== browserSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"browser driver returned an observation outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return BrowserActionReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n browserSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.browserSessionId !== browserSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n );\n },\n },\n });\n }\n\n observe(targetId: string): Promise<BrowserObservationValue> {\n return this.core.observe(targetId);\n }\n\n run(command: BrowserActionCommandValue): Promise<BrowserActionReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): BrowserActionReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): BrowserOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverBrowserOperationJournalRecord(\n record: BrowserOperationJournalRecord,\n settledAt: string,\n): BrowserOperationJournalRecord {\n const receipt = BrowserActionReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"browser\", (value) =>\n BrowserActionReceipt.parse(value),\n ),\n };\n}\n\nexport type BrowserProtectedAuthDriver = {\n target(targetId: string): Promise<BrowserTargetValue | null>;\n observe(targetId: string): Promise<BrowserProtectedAuthObservationValue>;\n validate?(\n command: BrowserProtectedAuthFillCommandValue,\n target: BrowserTargetValue,\n ): Promise<void> | void;\n dispatch(\n command: BrowserProtectedAuthFillCommandValue,\n ): Promise<BrowserProtectedAuthObservationValue>;\n};\n\nexport type BrowserProtectedAuthAuthority = {\n authorizeDispatch(command: BrowserProtectedAuthFillCommandValue): Promise<void> | void;\n};\n\nexport type BrowserProtectedAuthOperationJournalRecord =\n InteractionOperationJournalRecord<BrowserProtectedAuthFillReceiptValue>;\n\nexport type BrowserProtectedAuthControllerOptions = {\n browserSessionId: string;\n controllerGeneration: string;\n driver: BrowserProtectedAuthDriver;\n authority?: BrowserProtectedAuthAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly BrowserProtectedAuthOperationJournalRecord[];\n onJournalRecord?: (record: BrowserProtectedAuthOperationJournalRecord) => Promise<void> | void;\n};\n\n/** Secret-bearing commands are admitted only through this controller-private\n * authority. Its durable digest binds all semantics plus credential version,\n * but deliberately excludes ephemeral password/TOTP value bytes. */\nexport class BrowserProtectedAuthController {\n private readonly core: InteractionControllerCore<\n BrowserProtectedAuthFillCommandValue,\n BrowserTargetValue,\n BrowserProtectedAuthObservationValue,\n BrowserProtectedAuthFillReceiptValue\n >;\n\n constructor(options: BrowserProtectedAuthControllerOptions) {\n const { browserSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n commandDigest: protectedAuthCommandDigest,\n adapter: {\n resourceLabel: \"browser protected fill\",\n parseCommand: (value) => BrowserProtectedAuthFillCommand.parse(value),\n parseTarget: (value) => BrowserTarget.parse(value),\n parseObservation: (value) => BrowserProtectedAuthObservation.parse(value),\n parseReceipt: (value) => BrowserProtectedAuthFillReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.browserSessionId !== browserSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"protected fill targets another browser session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"protected fill targets a stale browser controller\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.browserSessionId !== browserSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"protected-fill target belongs to a stale browser controller\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"browser target changed before protected fill\",\n true,\n );\n }\n if (command.expectedDocumentGeneration !== target.documentGeneration) {\n throw new InteractionControllerError(\n \"document_stale\",\n \"browser document changed before protected fill\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.target.id !== targetId ||\n observation.target.browserSessionId !== browserSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"protected-fill driver returned a result outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return BrowserProtectedAuthFillReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n browserSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.browserSessionId !== browserSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored protected-fill operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"browser protected fill\", (value) =>\n BrowserProtectedAuthFillReceipt.parse(value),\n );\n },\n },\n });\n }\n\n run(\n command: BrowserProtectedAuthFillCommandValue,\n ): Promise<BrowserProtectedAuthFillReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): BrowserProtectedAuthFillReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): BrowserProtectedAuthOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverBrowserProtectedAuthOperationJournalRecord(\n record: BrowserProtectedAuthOperationJournalRecord,\n settledAt: string,\n): BrowserProtectedAuthOperationJournalRecord {\n const receipt = BrowserProtectedAuthFillReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"browser protected fill\", (value) =>\n BrowserProtectedAuthFillReceipt.parse(value),\n ),\n };\n}\n\nfunction protectedAuthCommandDigest(command: BrowserProtectedAuthFillCommandValue): string {\n const { fields, ...metadata } = command;\n const secretFree = {\n ...metadata,\n fields: fields.map(({ value: _value, ...field }) => field),\n };\n return createHash(\"sha256\").update(canonicalJson(secretFree), \"utf8\").digest(\"hex\");\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .filter(([, entry]) => entry !== undefined)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n\nexport type ComputerInteractionDriver = {\n target(targetId: string): Promise<ComputerTargetValue | null>;\n observe(targetId: string): Promise<ComputerObservationValue>;\n validate?(command: ComputerActionCommandValue, target: ComputerTargetValue): Promise<void> | void;\n dispatch(command: ComputerActionCommandValue): Promise<ComputerObservationValue | null>;\n};\n\nexport type ComputerInteractionAuthority = {\n authorizeDispatch(command: ComputerActionCommandValue): Promise<void> | void;\n};\n\nexport type ComputerOperationJournalRecord =\n InteractionOperationJournalRecord<ComputerActionReceiptValue>;\n\nexport type ComputerInteractionControllerOptions = {\n computerSessionId: string;\n controllerGeneration: string;\n driver: ComputerInteractionDriver;\n authority?: ComputerInteractionAuthority;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly ComputerOperationJournalRecord[];\n onJournalRecord?: (record: ComputerOperationJournalRecord) => Promise<void> | void;\n};\n\n/** Placement-resident ComputerSession mutation authority. Linux AT-SPI/X11,\n * macOS AX/ScreenCaptureKit, and later UIA adapters share this exact core. */\nexport class ComputerInteractionController {\n private readonly core: InteractionControllerCore<\n ComputerActionCommandValue,\n ComputerTargetValue,\n ComputerObservationValue,\n ComputerActionReceiptValue\n >;\n\n constructor(options: ComputerInteractionControllerOptions) {\n const { computerSessionId, controllerGeneration } = options;\n this.core = new InteractionControllerCore({\n driver: options.driver,\n ...(options.authority ? { authority: options.authority } : {}),\n ...(options.maxJournalEntries !== undefined\n ? { maxJournalEntries: options.maxJournalEntries }\n : {}),\n ...(options.now ? { now: options.now } : {}),\n ...(options.initialJournal ? { initialJournal: options.initialJournal } : {}),\n ...(options.onJournalRecord ? { onJournalRecord: options.onJournalRecord } : {}),\n adapter: {\n resourceLabel: \"computer\",\n parseCommand: (value) => ComputerActionCommand.parse(value),\n parseTarget: (value) => ComputerTarget.parse(value),\n parseObservation: (value) => ComputerObservation.parse(value),\n parseReceipt: (value) => ComputerActionReceipt.parse(value),\n assertCommandAuthority(command) {\n if (command.computerSessionId !== computerSessionId) {\n throw new InteractionControllerError(\n \"resource_not_found\",\n \"computer command targets another computer session\",\n );\n }\n if (command.controllerGeneration !== controllerGeneration) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer command targets a stale controller generation\",\n );\n }\n },\n assertTargetAuthority(target) {\n if (\n target.computerSessionId !== computerSessionId ||\n target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"controller_stale\",\n \"computer target belongs to a stale controller generation\",\n );\n }\n },\n assertExpectedGenerations(command, target) {\n if (command.expectedTargetGeneration !== target.targetGeneration) {\n throw new InteractionControllerError(\n \"target_stale\",\n \"computer target changed before the command could dispatch\",\n true,\n );\n }\n },\n assertObservationAuthority(observation, targetId) {\n if (\n observation.computerSessionId !== computerSessionId ||\n observation.target.id !== targetId ||\n observation.target.computerSessionId !== computerSessionId ||\n observation.target.controllerGeneration !== controllerGeneration\n ) {\n throw new InteractionControllerError(\n \"driver_failed\",\n \"computer driver returned an observation outside controller authority\",\n );\n }\n },\n makeReceipt(input) {\n return ComputerActionReceipt.parse({\n protocolVersion: 1,\n operationId: input.command.operationId,\n computerSessionId,\n controllerGeneration,\n targetId: input.command.targetId,\n state: input.state,\n dispatchedAt: input.dispatchedAt,\n settledAt: input.settledAt,\n observation: input.observation,\n error: input.error,\n });\n },\n recoverReceipt(receipt, settledAt) {\n if (\n receipt.computerSessionId !== computerSessionId ||\n receipt.controllerGeneration !== controllerGeneration\n ) {\n throw new Error(\n `restored operation ${receipt.operationId} is outside controller authority`,\n );\n }\n return recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerActionReceipt.parse(value),\n );\n },\n },\n });\n }\n\n observe(targetId: string): Promise<ComputerObservationValue> {\n return this.core.observe(targetId);\n }\n\n run(command: ComputerActionCommandValue): Promise<ComputerActionReceiptValue> {\n return this.core.run(command);\n }\n\n receipt(operationId: string): ComputerActionReceiptValue | null {\n return this.core.receipt(operationId);\n }\n\n journalSnapshot(): ComputerOperationJournalRecord[] {\n return this.core.journalSnapshot();\n }\n\n waitForIdle(): Promise<void> {\n return this.core.waitForIdle();\n }\n}\n\nexport function recoverComputerOperationJournalRecord(\n record: ComputerOperationJournalRecord,\n settledAt: string,\n): ComputerOperationJournalRecord {\n const receipt = ComputerActionReceipt.parse(record.receipt);\n return {\n ...record,\n receipt: recoverInteractionReceipt(receipt, settledAt, \"computer\", (value) =>\n ComputerActionReceipt.parse(value),\n ),\n };\n}\n","import { createHash } from \"node:crypto\";\nimport type { InteractionError, InteractionOperationState } from \"@opengeni/contracts\";\n\nexport type InteractionControllerErrorCode = InteractionError[\"code\"] | \"journal_full\";\n\n/** A safe, typed rejection known not to have dispatched a side effect. */\nexport class InteractionControllerError extends Error {\n constructor(\n readonly code: InteractionControllerErrorCode,\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionControllerError\";\n }\n}\n\n/** Driver proof that a dispatched command definitively failed without an ambiguous outcome. */\nexport class InteractionDefiniteDriverError extends Error {\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionDefiniteDriverError\";\n }\n}\n\n/** Driver proof that dispatch occurred but the exact native outcome could not\n * be confirmed. Unlike an arbitrary transport exception, this preserves the\n * adapter's bounded, user-actionable diagnosis without pretending certainty. */\nexport class InteractionOutcomeUnknownDriverError extends Error {\n constructor(\n readonly code: InteractionError[\"code\"],\n message: string,\n readonly retryable = false,\n ) {\n super(message);\n this.name = \"InteractionOutcomeUnknownDriverError\";\n }\n}\n\nexport type InteractionCoreCommand = {\n operationId: string;\n controllerGeneration: string;\n targetId: string;\n};\n\nexport type InteractionCoreTarget = {\n id: string;\n controllerGeneration: string;\n};\n\nexport type InteractionCoreObservation<TTarget extends InteractionCoreTarget> = {\n target: TTarget;\n};\n\nexport type InteractionCoreReceipt<TObservation> = {\n operationId: string;\n controllerGeneration: string;\n targetId: string;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n};\n\nexport type InteractionOperationJournalRecord<TReceipt> = {\n operationId: string;\n commandDigest: string;\n receipt: TReceipt;\n};\n\ntype InteractionDriver<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n> = {\n target(targetId: string): Promise<TTarget | null>;\n observe(targetId: string): Promise<TObservation>;\n validate?(command: TCommand, target: TTarget): Promise<void> | void;\n dispatch(command: TCommand): Promise<TObservation | null>;\n};\n\ntype InteractionCoreAdapter<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n resourceLabel: string;\n parseCommand(value: unknown): TCommand;\n parseTarget(value: unknown): TTarget;\n parseObservation(value: unknown): TObservation;\n parseReceipt(value: unknown): TReceipt;\n assertCommandAuthority(command: TCommand): void;\n assertTargetAuthority(target: TTarget): void;\n assertExpectedGenerations(command: TCommand, target: TTarget): void;\n assertObservationAuthority(observation: TObservation, targetId: string): void;\n makeReceipt(input: {\n command: TCommand;\n state: InteractionOperationState;\n dispatchedAt: string | null;\n settledAt: string | null;\n observation: TObservation | null;\n error: InteractionError | null;\n }): TReceipt;\n recoverReceipt(receipt: TReceipt, settledAt: string): TReceipt;\n};\n\ntype InteractionCoreAuthority<TCommand> = {\n authorizeDispatch(command: TCommand): Promise<void> | void;\n};\n\nexport type InteractionControllerCoreOptions<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> = {\n driver: InteractionDriver<TCommand, TTarget, TObservation>;\n adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n authority?: InteractionCoreAuthority<TCommand>;\n maxJournalEntries?: number;\n now?: () => Date;\n initialJournal?: readonly InteractionOperationJournalRecord<TReceipt>[];\n onJournalRecord?: (record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void;\n /** Override only when a private command contains ephemeral secret material.\n * The callback must bind every non-secret semantic input while excluding the\n * value bytes themselves and return lowercase SHA-256. */\n commandDigest?: (command: TCommand) => string;\n};\n\ntype JournalEntry<TReceipt> = InteractionOperationJournalRecord<TReceipt> & {\n completion: Promise<TReceipt>;\n preparationPersisted: Promise<boolean>;\n};\n\nconst terminalStates = new Set<InteractionOperationState>([\n \"completed\",\n \"failed\",\n \"outcome_unknown\",\n]);\n\n/**\n * Resource-neutral placement mutation authority. Public Browser and Computer\n * controllers supply only their schemas and generation semantics; journaling,\n * idempotency, target-local serialization, and crash policy stay identical.\n */\nexport class InteractionControllerCore<\n TCommand extends InteractionCoreCommand,\n TTarget extends InteractionCoreTarget,\n TObservation extends InteractionCoreObservation<TTarget>,\n TReceipt extends InteractionCoreReceipt<TObservation>,\n> {\n private readonly driver: InteractionDriver<TCommand, TTarget, TObservation>;\n private readonly adapter: InteractionCoreAdapter<TCommand, TTarget, TObservation, TReceipt>;\n private readonly authority: InteractionCoreAuthority<TCommand> | undefined;\n private readonly maxJournalEntries: number;\n private readonly now: () => Date;\n private readonly onJournalRecord:\n | ((record: InteractionOperationJournalRecord<TReceipt>) => Promise<void> | void)\n | undefined;\n private readonly commandDigest: (command: TCommand) => string;\n private readonly journal = new Map<string, JournalEntry<TReceipt>>();\n private readonly targetTails = new Map<string, Promise<void>>();\n\n constructor(\n options: InteractionControllerCoreOptions<TCommand, TTarget, TObservation, TReceipt>,\n ) {\n this.driver = options.driver;\n this.adapter = options.adapter;\n this.authority = options.authority;\n this.maxJournalEntries = options.maxJournalEntries ?? 10_000;\n this.now = options.now ?? (() => new Date());\n this.onJournalRecord = options.onJournalRecord;\n this.commandDigest = options.commandDigest ?? digestJson;\n if (!Number.isSafeInteger(this.maxJournalEntries) || this.maxJournalEntries < 1) {\n throw new Error(\"maxJournalEntries must be a positive safe integer\");\n }\n for (const record of options.initialJournal ?? []) this.restoreJournalRecord(record);\n }\n\n async observe(targetId: string): Promise<TObservation> {\n const target = await this.requireCurrentTarget(targetId);\n const observed = this.adapter.parseObservation(await this.driver.observe(target.id));\n this.adapter.assertObservationAuthority(observed, target.id);\n return observed;\n }\n\n run(commandInput: TCommand): Promise<TReceipt> {\n const command = this.adapter.parseCommand(commandInput);\n this.adapter.assertCommandAuthority(command);\n const commandDigest = this.commandDigest(command);\n if (!/^[0-9a-f]{64}$/u.test(commandDigest)) {\n throw new Error(`${this.adapter.resourceLabel} command digest must be lowercase SHA-256`);\n }\n const existing = this.journal.get(command.operationId);\n if (existing) {\n if (existing.commandDigest !== commandDigest) {\n throw new InteractionControllerError(\n \"operation_conflict\",\n `operation id is already bound to a different ${this.adapter.resourceLabel} command`,\n );\n }\n return existing.completion;\n }\n\n this.makeJournalSpace();\n const prepared = this.makeReceipt(command, \"prepared\", null, null, null, null);\n const entry: JournalEntry<TReceipt> = {\n operationId: command.operationId,\n commandDigest,\n receipt: prepared,\n completion: Promise.resolve(prepared),\n preparationPersisted: this.publish(command.operationId, commandDigest, prepared).then(\n () => true,\n () => false,\n ),\n };\n this.journal.set(command.operationId, entry);\n\n const previous = this.targetTails.get(command.targetId) ?? Promise.resolve();\n entry.completion = previous.then(async () => await this.execute(entry, command));\n const tail = entry.completion.then(\n () => undefined,\n () => undefined,\n );\n this.targetTails.set(command.targetId, tail);\n void tail.finally(() => {\n if (this.targetTails.get(command.targetId) === tail)\n this.targetTails.delete(command.targetId);\n });\n return entry.completion;\n }\n\n receipt(operationId: string): TReceipt | null {\n return this.journal.get(operationId)?.receipt ?? null;\n }\n\n journalSnapshot(): InteractionOperationJournalRecord<TReceipt>[] {\n return [...this.journal.values()].map(({ operationId, commandDigest, receipt }) => ({\n operationId,\n commandDigest,\n receipt,\n }));\n }\n\n /** Wait until every command already admitted to a target queue settles.\n * Callers must fence new dispatch through `authority` before awaiting this. */\n async waitForIdle(): Promise<void> {\n while (this.targetTails.size > 0) await Promise.all([...this.targetTails.values()]);\n }\n\n private async execute(entry: JournalEntry<TReceipt>, command: TCommand): Promise<TReceipt> {\n if (!(await entry.preparationPersisted)) {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal rejected the command before dispatch`,\n );\n }\n\n try {\n await this.authority?.authorizeDispatch(command);\n const target = await this.requireCurrentTarget(command.targetId);\n this.adapter.assertExpectedGenerations(command, target);\n await this.driver.validate?.(command, target);\n } catch (error) {\n return await this.settle(\n entry,\n this.makeReceipt(\n command,\n \"failed\",\n null,\n this.timestamp(),\n null,\n safePredispatchError(error, this.adapter.resourceLabel),\n ),\n );\n }\n\n const dispatchedAt = this.timestamp();\n const dispatched = this.makeReceipt(command, \"dispatched\", dispatchedAt, null, null, null);\n try {\n await this.publish(entry.operationId, entry.commandDigest, dispatched);\n entry.receipt = dispatched;\n } catch {\n return await this.failBeforeDispatch(\n entry,\n command,\n `${this.adapter.resourceLabel} operation journal became unavailable before dispatch`,\n );\n }\n\n try {\n const dispatchedObservation = await this.driver.dispatch(command);\n const observation =\n dispatchedObservation === null\n ? null\n : this.adapter.parseObservation(dispatchedObservation);\n if (observation) this.adapter.assertObservationAuthority(observation, command.targetId);\n const completed = this.makeReceipt(\n command,\n \"completed\",\n dispatchedAt,\n this.timestamp(),\n observation,\n null,\n );\n try {\n await this.publish(entry.operationId, entry.commandDigest, completed);\n entry.receipt = completed;\n return completed;\n } catch {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command completed but its durable outcome could not be recorded`,\n retryable: false,\n }),\n );\n }\n } catch (error) {\n if (error instanceof InteractionDefiniteDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"failed\", dispatchedAt, this.timestamp(), null, {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n }),\n );\n }\n if (error instanceof InteractionOutcomeUnknownDriverError) {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n }),\n );\n }\n return await this.settle(\n entry,\n this.makeReceipt(command, \"outcome_unknown\", dispatchedAt, this.timestamp(), null, {\n code: \"controller_lost\",\n message: `${this.adapter.resourceLabel} command outcome is unknown after dispatch`,\n retryable: false,\n }),\n );\n }\n }\n\n private async requireCurrentTarget(targetId: string): Promise<TTarget> {\n const target = await this.driver.target(targetId);\n if (!target) {\n throw new InteractionControllerError(\n \"target_not_found\",\n `${this.adapter.resourceLabel} target does not exist`,\n );\n }\n const parsed = this.adapter.parseTarget(target);\n this.adapter.assertTargetAuthority(parsed);\n return parsed;\n }\n\n private makeReceipt(\n command: TCommand,\n state: InteractionOperationState,\n dispatchedAt: string | null,\n settledAt: string | null,\n observation: TObservation | null,\n error: InteractionError | null,\n ): TReceipt {\n return this.adapter.makeReceipt({\n command,\n state,\n dispatchedAt,\n settledAt,\n observation,\n error,\n });\n }\n\n private async settle(entry: JournalEntry<TReceipt>, receipt: TReceipt): Promise<TReceipt> {\n entry.receipt = receipt;\n try {\n await this.publish(entry.operationId, entry.commandDigest, receipt);\n } catch {\n // Controller-lifetime terminal truth remains authoritative. A restored\n // dispatched receipt is always recovered as outcome_unknown, never replayed.\n }\n return receipt;\n }\n\n private async failBeforeDispatch(\n entry: JournalEntry<TReceipt>,\n command: TCommand,\n message: string,\n ): Promise<TReceipt> {\n return await this.settle(\n entry,\n this.makeReceipt(command, \"failed\", null, this.timestamp(), null, {\n code: \"driver_failed\",\n message,\n retryable: true,\n }),\n );\n }\n\n private async publish(\n operationId: string,\n commandDigest: string,\n receipt: TReceipt,\n ): Promise<void> {\n await this.onJournalRecord?.({ operationId, commandDigest, receipt });\n }\n\n private timestamp(): string {\n return this.now().toISOString();\n }\n\n private makeJournalSpace(): void {\n while (this.journal.size >= this.maxJournalEntries) {\n const terminal = [...this.journal.entries()].find(([, entry]) =>\n terminalStates.has(entry.receipt.state),\n );\n if (!terminal) {\n throw new InteractionControllerError(\n \"journal_full\",\n `${this.adapter.resourceLabel} operation journal has no safely evictable terminal entry`,\n true,\n );\n }\n this.journal.delete(terminal[0]);\n }\n }\n\n private restoreJournalRecord(record: InteractionOperationJournalRecord<TReceipt>): void {\n if (this.journal.has(record.operationId)) {\n throw new Error(`duplicate restored operation id: ${record.operationId}`);\n }\n const parsed = this.adapter.parseReceipt(record.receipt);\n if (parsed.operationId !== record.operationId) {\n throw new Error(`restored operation ${record.operationId} has another receipt id`);\n }\n const receipt = this.adapter.recoverReceipt(parsed, this.timestamp());\n const entry: JournalEntry<TReceipt> = {\n operationId: record.operationId,\n commandDigest: record.commandDigest,\n receipt,\n completion: Promise.resolve(receipt),\n preparationPersisted: Promise.resolve(true),\n };\n this.journal.set(record.operationId, entry);\n }\n}\n\nexport function recoverInteractionReceipt<TReceipt extends InteractionCoreReceipt<unknown>>(\n receipt: TReceipt,\n settledAt: string,\n resourceLabel: string,\n parse: (value: unknown) => TReceipt,\n): TReceipt {\n if (terminalStates.has(receipt.state)) return receipt;\n return parse({\n ...receipt,\n state: receipt.state === \"dispatched\" ? \"outcome_unknown\" : \"failed\",\n settledAt,\n observation: null,\n error:\n receipt.state === \"dispatched\"\n ? {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted after command dispatch`,\n retryable: false,\n }\n : {\n code: \"controller_lost\",\n message: `${resourceLabel} controller restarted before command dispatch`,\n retryable: true,\n },\n });\n}\n\nfunction safePredispatchError(error: unknown, resourceLabel: string): InteractionError {\n if (error instanceof InteractionControllerError && error.code !== \"journal_full\") {\n return {\n code: error.code,\n message: error.message,\n retryable: error.retryable,\n };\n }\n return {\n code: \"driver_failed\",\n message: `${resourceLabel} command failed before dispatch`,\n retryable: false,\n };\n}\n\nfunction digestJson(value: unknown): string {\n return createHash(\"sha256\").update(canonicalJson(value), \"utf8\").digest(\"hex\");\n}\n\nfunction canonicalJson(value: unknown): string {\n return JSON.stringify(canonicalJsonValue(value));\n}\n\nfunction canonicalJsonValue(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonicalJsonValue);\n if (value !== null && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value as Record<string, unknown>)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonicalJsonValue(entry)]),\n );\n }\n return value;\n}\n"],"mappings":"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","names":["createHash","createHash","canonicalJson","canonicalJsonValue"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/interaction",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.12-canary.0",
|
|
4
4
|
"description": "Provider-neutral browser and computer interaction controller for OpenGeni.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"prepublishOnly": "bash ../../scripts/prepublish-guard"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@opengeni/contracts": "^
|
|
37
|
+
"@opengeni/contracts": "^2.3.0-canary.0"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
40
40
|
"node": ">=18"
|
package/src/controller-core.ts
CHANGED
|
@@ -27,6 +27,20 @@ export class InteractionDefiniteDriverError extends Error {
|
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/** Driver proof that dispatch occurred but the exact native outcome could not
|
|
31
|
+
* be confirmed. Unlike an arbitrary transport exception, this preserves the
|
|
32
|
+
* adapter's bounded, user-actionable diagnosis without pretending certainty. */
|
|
33
|
+
export class InteractionOutcomeUnknownDriverError extends Error {
|
|
34
|
+
constructor(
|
|
35
|
+
readonly code: InteractionError["code"],
|
|
36
|
+
message: string,
|
|
37
|
+
readonly retryable = false,
|
|
38
|
+
) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = "InteractionOutcomeUnknownDriverError";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
30
44
|
export type InteractionCoreCommand = {
|
|
31
45
|
operationId: string;
|
|
32
46
|
controllerGeneration: string;
|
|
@@ -321,6 +335,16 @@ export class InteractionControllerCore<
|
|
|
321
335
|
}),
|
|
322
336
|
);
|
|
323
337
|
}
|
|
338
|
+
if (error instanceof InteractionOutcomeUnknownDriverError) {
|
|
339
|
+
return await this.settle(
|
|
340
|
+
entry,
|
|
341
|
+
this.makeReceipt(command, "outcome_unknown", dispatchedAt, this.timestamp(), null, {
|
|
342
|
+
code: error.code,
|
|
343
|
+
message: error.message,
|
|
344
|
+
retryable: error.retryable,
|
|
345
|
+
}),
|
|
346
|
+
);
|
|
347
|
+
}
|
|
324
348
|
return await this.settle(
|
|
325
349
|
entry,
|
|
326
350
|
this.makeReceipt(command, "outcome_unknown", dispatchedAt, this.timestamp(), null, {
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
InteractionControllerCore,
|
|
28
28
|
InteractionControllerError,
|
|
29
29
|
InteractionDefiniteDriverError,
|
|
30
|
+
InteractionOutcomeUnknownDriverError,
|
|
30
31
|
recoverInteractionReceipt,
|
|
31
32
|
type InteractionControllerErrorCode,
|
|
32
33
|
type InteractionOperationJournalRecord,
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
export {
|
|
36
37
|
InteractionControllerError,
|
|
37
38
|
InteractionDefiniteDriverError,
|
|
39
|
+
InteractionOutcomeUnknownDriverError,
|
|
38
40
|
type InteractionControllerErrorCode,
|
|
39
41
|
};
|
|
40
42
|
|