diff --git a/dist/bindings.d.ts b/dist/bindings.d.ts index 15a8f91..3520763 100644 --- a/dist/bindings.d.ts +++ b/dist/bindings.d.ts @@ -1,11 +1,6 @@ import { type Value } from "./camino/api_pb.js"; import { type RuntimeHandler, type DerivedHandler } from "./index.js"; -declare const referenceBrand: unique symbol; -export type QxObjectRef = string & { - readonly [referenceBrand]: { - readonly [K in Identity]: true; - }; -}; +export type { QxObjectRef } from "./references.js"; declare const watchBrand: unique symbol; export type QxWatchHandle = string & { readonly [watchBrand]: true; @@ -20,6 +15,15 @@ export type QxDerived = { kind: "derived"; get: QxHandler; }; +export type QxSession = { + id: string; + run(work: (context: C) => Promise): Promise; + close(): Promise; +}; +export type QxContextLifecycle = { + signal?: AbortSignal; + openSession?: () => Promise>; +}; export declare const qxDerived: (get: QxHandler) => QxDerived; /** Versioned binding ABI. This mirrors the language-neutral value IR. */ export type QxValueType = { @@ -72,5 +76,4 @@ export declare const decodeQxValue: (type: QxValueType, value: Value | undefined export declare const encodeQxValue: (type: QxValueType, value: any, messages: QxMessages) => Value; /** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */ export declare const bindQxHandler: (spec: QxHandlerSpec, handler: QxHandler | QxDerived, messages: QxMessages) => RuntimeHandler | DerivedHandler; -export {}; //# sourceMappingURL=bindings.d.ts.map \ No newline at end of file diff --git a/dist/bindings.d.ts.map b/dist/bindings.d.ts.map index 77c3341..ffb6391 100644 --- a/dist/bindings.d.ts.map +++ b/dist/bindings.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"bindings.d.ts","sourceRoot":"","sources":["../src/bindings.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/bindings.js b/dist/bindings.js index 6277cdc..eec1164 100644 --- a/dist/bindings.js +++ b/dist/bindings.js @@ -1,6 +1,7 @@ import { create } from "@bufbuild/protobuf"; import { ValueSchema, ObjectValueSchema } from "./camino/api_pb.js"; import { derived, jsToProtoValue, liveValue, protoValueToJs } from "./index.js"; +import { assertReferenceFree, referenceToWire } from "./references.js"; export const qxDerived = (get) => ({ kind: "derived", get }); // Conversion belongs at the binding boundary. It does not add orchestrator validation. export const decodeQxValue = (type, value, messages) => { @@ -15,8 +16,19 @@ export const decodeQxValue = (type, value, messages) => { throw new Error("Expected QX list"); return value.kind.value.values.map((entry) => decodeQxValue(type.value, entry, messages)); } - if (type.kind === "message") - return requireMessage(messages, type.descriptorId).decode(value); + if (type.kind === "message") { + assertReferenceFree(protoValueToJs(value)); + const decoded = requireMessage(messages, type.descriptorId).decode(value); + assertReferenceFree(decoded); + return decoded; + } + if (type.kind === "object-ref") { + if (value.kind.case !== "refValue") + throw new Error("Expected a declared RPC object reference"); + return protoValueToJs(value); + } + if (value.kind.case === "refValue") + throw new Error("Reference supplied to a non-reference value"); if (type.kind === "scalar") { if (type.name === "int64" || type.name === "uint64") { if (value.kind.case !== "integerValue") @@ -44,10 +56,16 @@ export const encodeQxValue = (type, value, messages) => { return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages); if (type.kind === "list") return jsToProtoValue(value.map((entry) => liveValue(encodeQxValue(type.value, entry, messages)))); - if (type.kind === "message") - return requireMessage(messages, type.descriptorId).encode(value); - if (type.kind === "object-ref") - return jsToProtoValue({ $quixosRef: value }); + if (type.kind === "object-ref") { + referenceToWire(value); + return jsToProtoValue(value); + } + assertReferenceFree(value); + if (type.kind === "message") { + const encoded = requireMessage(messages, type.descriptorId).encode(value); + assertReferenceFree(protoValueToJs(encoded)); + return encoded; + } return jsToProtoValue(value); }; const inputValue = (context, type) => { @@ -69,7 +87,7 @@ const inputFields = (type, value, messages) => { }; /** The sole unchecked cast connects generated contracts to the dynamic RPC runtime. */ export const bindQxHandler = (spec, handler, messages) => { - const execute = async (raw) => { + const bindContext = (raw) => { const ports = Object.fromEntries(Object.entries(spec.ports).map(([name, port]) => { switch (port.kind) { case "state": { @@ -81,7 +99,9 @@ export const bindQxHandler = (spec, handler, messages) => { } case "edge": { const edge = raw.edge(port.id); - return [name, Object.fromEntries(port.primitives.map((primitive) => [primitive, edge[primitive]]))]; + return [name, { ...Object.fromEntries(port.primitives.map((primitive) => [primitive, edge[primitive]])), + ...(port.primitives.includes("resolve") ? { collection: edge.collection } : {}), + ...(port.primitives.includes("resolve") && port.primitives.includes("connect") && port.primitives.includes("disconnect") ? { replace: edge.replace } : {}) }]; } case "interface": { const target = raw.interface(port.id); @@ -92,8 +112,16 @@ export const bindQxHandler = (spec, handler, messages) => { case "constructor": return [name, { construct: (input) => raw.constructor(port.id).construct(inputFields(port.inputType, input, messages)) }]; } })); - const context = { objectId: raw.objectId, + return { objectId: raw.objectId, signal: raw.signal, + ...(raw.openSession ? { openSession: async () => { + const session = await raw.openSession(); + return { id: session.id, close: () => session.close(), + run: (work) => session.run((next) => work(bindContext(next))) }; + } } : {}), input: decodeQxValue(spec.inputType, inputValue(raw, spec.inputType), messages), ports }; + }; + const execute = async (raw) => { + const context = bindContext(raw); const value = await (typeof handler === "function" ? handler(context) : handler.get(context)); return liveValue(encodeQxValue(spec.eventType ?? spec.outputType, value, messages)); }; diff --git a/dist/camino/api_pb.d.ts b/dist/camino/api_pb.d.ts index ff9e965..fe35029 100644 --- a/dist/camino/api_pb.d.ts +++ b/dist/camino/api_pb.d.ts @@ -542,6 +542,78 @@ export type DisconnectEdgeResponse = Message<"camino.DisconnectEdgeResponse"> & * Use `create(DisconnectEdgeResponseSchema)` to create a new message. */ export declare const DisconnectEdgeResponseSchema: GenMessage; +/** + * @generated from message camino.CollectionEntry + */ +export type CollectionEntry = Message<"camino.CollectionEntry"> & { + /** + * Existing entry identity to preserve; empty allocates a new canonical edge. + * + * @generated from field: string edge_id = 1; + */ + edgeId: string; + /** + * @generated from field: string target_object_id = 2; + */ + targetObjectId: string; + /** + * @generated from field: camino.Value key = 3; + */ + key?: Value | undefined; +}; +/** + * Describes the message camino.CollectionEntry. + * Use `create(CollectionEntrySchema)` to create a new message. + */ +export declare const CollectionEntrySchema: GenMessage; +/** + * @generated from message camino.ReadCollectionResponse + */ +export type ReadCollectionResponse = Message<"camino.ReadCollectionResponse"> & { + /** + * @generated from field: uint64 revision = 1; + */ + revision: bigint; + /** + * @generated from field: repeated camino.CollectionEntry entries = 2; + */ + entries: CollectionEntry[]; +}; +/** + * Describes the message camino.ReadCollectionResponse. + * Use `create(ReadCollectionResponseSchema)` to create a new message. + */ +export declare const ReadCollectionResponseSchema: GenMessage; +/** + * @generated from message camino.ReplaceCollectionRequest + */ +export type ReplaceCollectionRequest = Message<"camino.ReplaceCollectionRequest"> & { + /** + * @generated from field: string object_id = 1; + */ + objectId: string; + /** + * @generated from field: string edge_type_id = 2; + */ + edgeTypeId: string; + /** + * @generated from field: string projection_id = 3; + */ + projectionId: string; + /** + * @generated from field: uint64 expected_revision = 4; + */ + expectedRevision: bigint; + /** + * @generated from field: repeated camino.CollectionEntry entries = 5; + */ + entries: CollectionEntry[]; +}; +/** + * Describes the message camino.ReplaceCollectionRequest. + * Use `create(ReplaceCollectionRequestSchema)` to create a new message. + */ +export declare const ReplaceCollectionRequestSchema: GenMessage; /** * @generated from message camino.ListOpsRequest */ @@ -586,6 +658,12 @@ export type WatchObjectRequest = Message<"camino.WatchObjectRequest"> & { * @generated from field: bool include_snapshot = 3; */ includeSnapshot: boolean; + /** + * Managed runtimes must watch only their injected attachments. + * + * @generated from field: repeated string attachment_ids = 4; + */ + attachmentIds: string[]; }; /** * Describes the message camino.WatchObjectRequest. @@ -696,6 +774,14 @@ export type CaminoEdge = Message<"camino.CaminoEdge"> & { * @generated from field: string created_at = 9; */ createdAt: string; + /** + * @generated from field: string first_key_json = 10; + */ + firstKeyJson: string; + /** + * @generated from field: string second_key_json = 11; + */ + secondKeyJson: string; }; /** * Describes the message camino.CaminoEdge. @@ -824,6 +910,22 @@ export declare const CaminoService: GenService<{ input: typeof DisconnectEdgeRequestSchema; output: typeof DisconnectEdgeResponseSchema; }; + /** + * @generated from rpc camino.CaminoService.ReadCollection + */ + readCollection: { + methodKind: "unary"; + input: typeof ResolveEdgeRequestSchema; + output: typeof ReadCollectionResponseSchema; + }; + /** + * @generated from rpc camino.CaminoService.ReplaceCollection + */ + replaceCollection: { + methodKind: "unary"; + input: typeof ReplaceCollectionRequestSchema; + output: typeof ReadCollectionResponseSchema; + }; /** * @generated from rpc camino.CaminoService.ListOps */ diff --git a/dist/camino/api_pb.d.ts.map b/dist/camino/api_pb.d.ts.map index 040f9e4..6240003 100644 --- a/dist/camino/api_pb.d.ts.map +++ b/dist/camino/api_pb.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"api_pb.d.ts","sourceRoot":"","sources":["../../src/camino/api_pb.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"api_pb.d.ts","sourceRoot":"","sources":["../../src/camino/api_pb.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/camino/api_pb.js b/dist/camino/api_pb.js index 670b83a..497bf6a 100644 --- a/dist/camino/api_pb.js +++ b/dist/camino/api_pb.js @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file camino/api.proto (package camino, syntax proto3) /* eslint-disable */ import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; @@ -6,7 +6,7 @@ import { file_camino_schema } from "./schema_pb.js"; /** * Describes the file camino/api.proto. */ -export const file_camino_api = /*@__PURE__*/ fileDesc("ChBjYW1pbm8vYXBpLnByb3RvEgZjYW1pbm8iCwoJTnVsbFZhbHVlInwKC09iamVjdFZhbHVlEi8KBmZpZWxkcxgBIAMoCzIfLmNhbWluby5PYmplY3RWYWx1ZS5GaWVsZHNFbnRyeRo8CgtGaWVsZHNFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIioKCUxpc3RWYWx1ZRIdCgZ2YWx1ZXMYASADKAsyDS5jYW1pbm8uVmFsdWUiHQoIUmVmVmFsdWUSEQoJb2JqZWN0X2lkGAEgASgJIjwKCUNyZHRWYWx1ZRIMCgR0eXBlGAEgASgJEhAKCGVuY29kaW5nGAIgASgJEg8KB3BheWxvYWQYAyABKAwiqAEKEFN0YXRlVmFsdWVTb3VyY2USEQoJb2JqZWN0X2lkGAEgASgJEg8KB3Nsb3RfaWQYAiABKAkSFwoPdmFsdWVfdHlwZV9qc29uGAMgASgJEhsKE3N0b3JhZ2VfcG9saWN5X2pzb24YBCABKAkSEAoIcmV2aXNpb24YBSABKAQSKAoNY3JkdF9zbmFwc2hvdBgGIAEoCzIRLmNhbWluby5DcmR0VmFsdWUiNgoLVmFsdWVTb3VyY2USJwoFc3RhdGUYASABKAsyGC5jYW1pbm8uU3RhdGVWYWx1ZVNvdXJjZSL5AgoFVmFsdWUSJwoKbnVsbF92YWx1ZRgBIAEoCzIRLmNhbWluby5OdWxsVmFsdWVIABIUCgpib29sX3ZhbHVlGAIgASgISAASFgoMbnVtYmVyX3ZhbHVlGAMgASgBSAASFgoMc3RyaW5nX3ZhbHVlGAQgASgJSAASFwoNaW50ZWdlcl92YWx1ZRgFIAEoCUgAEhUKC2J5dGVzX3ZhbHVlGAYgASgMSAASKwoMb2JqZWN0X3ZhbHVlGAcgASgLMhMuY2FtaW5vLk9iamVjdFZhbHVlSAASJwoKbGlzdF92YWx1ZRgIIAEoCzIRLmNhbWluby5MaXN0VmFsdWVIABIlCglyZWZfdmFsdWUYCSABKAsyEC5jYW1pbm8uUmVmVmFsdWVIABInCgpjcmR0X3ZhbHVlGAogASgLMhEuY2FtaW5vLkNyZHRWYWx1ZUgAEiMKBnNvdXJjZRgLIAEoCzITLmNhbWluby5WYWx1ZVNvdXJjZUIGCgRraW5kIkYKHUluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0EiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIkcKHkluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXNwb25zZRIlCgRwbGFuGAEgASgLMhcuY2FtaW5vLlBlcnNpc3RlbmNlUGxhbiIbChlHZXRQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0IkMKGkdldFBlcnNpc3RlbmNlUGxhblJlc3BvbnNlEiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIrABChNDcmVhdGVPYmplY3RSZXF1ZXN0Eg8KB2F0b21faWQYASABKAkSRAoNaW5pdGlhbF9zdGF0ZRgCIAMoCzItLmNhbWluby5DcmVhdGVPYmplY3RSZXF1ZXN0LkluaXRpYWxTdGF0ZUVudHJ5GkIKEUluaXRpYWxTdGF0ZUVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPAoUQ3JlYXRlT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCIlChBHZXRPYmplY3RSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCSI5ChFHZXRPYmplY3RSZXNwb25zZRIkCgZvYmplY3QYASABKAsyFC5jYW1pbm8uQ2FtaW5vT2JqZWN0IiUKEkxpc3RPYmplY3RzUmVxdWVzdBIPCgdhdG9tX2lkGAEgASgJIjwKE0xpc3RPYmplY3RzUmVzcG9uc2USJQoHb2JqZWN0cxgBIAMoCzIULmNhbWluby5DYW1pbm9PYmplY3QiNgoQUmVhZFN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCSIxChFSZWFkU3RhdGVSZXNwb25zZRIcCgV2YWx1ZRgBIAEoCzINLmNhbWluby5WYWx1ZSJxChFXcml0ZVN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCRIcCgV2YWx1ZRgDIAEoCzINLmNhbWluby5WYWx1ZRIaChJjbGllbnRfbXV0YXRpb25faWQYBCABKAkiWAoSV3JpdGVTdGF0ZVJlc3BvbnNlEhwKBXZhbHVlGAEgASgLMg0uY2FtaW5vLlZhbHVlEiQKBm9iamVjdBgCIAEoCzIULmNhbWluby5DYW1pbm9PYmplY3QiwAEKEkNvbm5lY3RFZGdlUmVxdWVzdBIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCRIRCglvYmplY3RfaWQYAyABKAkSGAoQdGFyZ2V0X29iamVjdF9pZBgEIAEoCRIUCgdvcmRpbmFsGAUgASgFSACIAQESGwoOdGFyZ2V0X29yZGluYWwYBiABKAVIAYgBAUIKCghfb3JkaW5hbEIRCg9fdGFyZ2V0X29yZGluYWwiNwoTQ29ubmVjdEVkZ2VSZXNwb25zZRIgCgRlZGdlGAEgASgLMhIuY2FtaW5vLkNhbWlub0VkZ2UiVAoSUmVzb2x2ZUVkZ2VSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCRIUCgxlZGdlX3R5cGVfaWQYAiABKAkSFQoNcHJvamVjdGlvbl9pZBgDIAEoCSI4ChNSZXNvbHZlRWRnZVJlc3BvbnNlEiEKBWVkZ2VzGAEgAygLMhIuY2FtaW5vLkNhbWlub0VkZ2UiKAoVRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Eg8KB2VkZ2VfaWQYASABKAkiKQoWRGlzY29ubmVjdEVkZ2VSZXNwb25zZRIPCgdlZGdlX2lkGAEgASgJIiMKDkxpc3RPcHNSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCSIwCg9MaXN0T3BzUmVzcG9uc2USHQoDb3BzGAEgAygLMhAuY2FtaW5vLkNhbWlub09wIlYKEldhdGNoT2JqZWN0UmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSEwoLYWZ0ZXJfb3BfaWQYAiABKAkSGAoQaW5jbHVkZV9zbmFwc2hvdBgDIAEoCCJrChBXYXRjaE9iamVjdEV2ZW50EhEKCW9iamVjdF9pZBgBIAEoCRImCghzbmFwc2hvdBgCIAEoCzIULmNhbWluby5DYW1pbm9PYmplY3QSHAoCb3AYAyABKAsyEC5jYW1pbm8uQ2FtaW5vT3Ai2QIKDENhbWlub09iamVjdBIKCgJpZBgBIAEoCRIPCgdhdG9tX2lkGAIgASgJEh0KFXdvcmtzcGFjZV9yZXZpc2lvbl9pZBgDIAEoCRISCgpjcmVhdGVkX2F0GAQgASgJEhIKCnVwZGF0ZWRfYXQYBSABKAkSLgoFc3RhdGUYBiADKAsyHy5jYW1pbm8uQ2FtaW5vT2JqZWN0LlN0YXRlRW50cnkSQQoPc3RhdGVfcmV2aXNpb25zGAcgAygLMiguY2FtaW5vLkNhbWlub09iamVjdC5TdGF0ZVJldmlzaW9uc0VudHJ5GjsKClN0YXRlRW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ARo1ChNTdGF0ZVJldmlzaW9uc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBDoCOAEijgIKCkNhbWlub0VkZ2USCgoCaWQYASABKAkSFAoMZWRnZV90eXBlX2lkGAIgASgJEhcKD2ZpcnN0X29iamVjdF9pZBgDIAEoCRIYChBzZWNvbmRfb2JqZWN0X2lkGAQgASgJEhsKE2ZpcnN0X3Byb2plY3Rpb25faWQYBSABKAkSHAoUc2Vjb25kX3Byb2plY3Rpb25faWQYBiABKAkSGgoNZmlyc3Rfb3JkaW5hbBgHIAEoBUgAiAEBEhsKDnNlY29uZF9vcmRpbmFsGAggASgFSAGIAQESEgoKY3JlYXRlZF9hdBgJIAEoCUIQCg5fZmlyc3Rfb3JkaW5hbEIRCg9fc2Vjb25kX29yZGluYWwimQEKCENhbWlub09wEgoKAmlkGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIPCgdvcF9raW5kGAMgASgJEh4KB3BheWxvYWQYBCABKAsyDS5jYW1pbm8uVmFsdWUSDQoFYWN0b3IYBSABKAkSEgoKY3JlYXRlZF9hdBgGIAEoCRIaChJjbGllbnRfbXV0YXRpb25faWQYByABKAkylQcKDUNhbWlub1NlcnZpY2USZwoWSW5zdGFsbFBlcnNpc3RlbmNlUGxhbhIlLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVxdWVzdBomLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USWwoSR2V0UGVyc2lzdGVuY2VQbGFuEiEuY2FtaW5vLkdldFBlcnNpc3RlbmNlUGxhblJlcXVlc3QaIi5jYW1pbm8uR2V0UGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USSQoMQ3JlYXRlT2JqZWN0EhsuY2FtaW5vLkNyZWF0ZU9iamVjdFJlcXVlc3QaHC5jYW1pbm8uQ3JlYXRlT2JqZWN0UmVzcG9uc2USQAoJR2V0T2JqZWN0EhguY2FtaW5vLkdldE9iamVjdFJlcXVlc3QaGS5jYW1pbm8uR2V0T2JqZWN0UmVzcG9uc2USRgoLTGlzdE9iamVjdHMSGi5jYW1pbm8uTGlzdE9iamVjdHNSZXF1ZXN0GhsuY2FtaW5vLkxpc3RPYmplY3RzUmVzcG9uc2USQAoJUmVhZFN0YXRlEhguY2FtaW5vLlJlYWRTdGF0ZVJlcXVlc3QaGS5jYW1pbm8uUmVhZFN0YXRlUmVzcG9uc2USQwoKV3JpdGVTdGF0ZRIZLmNhbWluby5Xcml0ZVN0YXRlUmVxdWVzdBoaLmNhbWluby5Xcml0ZVN0YXRlUmVzcG9uc2USRgoLQ29ubmVjdEVkZ2USGi5jYW1pbm8uQ29ubmVjdEVkZ2VSZXF1ZXN0GhsuY2FtaW5vLkNvbm5lY3RFZGdlUmVzcG9uc2USRgoLUmVzb2x2ZUVkZ2USGi5jYW1pbm8uUmVzb2x2ZUVkZ2VSZXF1ZXN0GhsuY2FtaW5vLlJlc29sdmVFZGdlUmVzcG9uc2USTwoORGlzY29ubmVjdEVkZ2USHS5jYW1pbm8uRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Gh4uY2FtaW5vLkRpc2Nvbm5lY3RFZGdlUmVzcG9uc2USOgoHTGlzdE9wcxIWLmNhbWluby5MaXN0T3BzUmVxdWVzdBoXLmNhbWluby5MaXN0T3BzUmVzcG9uc2USRQoLV2F0Y2hPYmplY3QSGi5jYW1pbm8uV2F0Y2hPYmplY3RSZXF1ZXN0GhguY2FtaW5vLldhdGNoT2JqZWN0RXZlbnQwAWIGcHJvdG8z", [file_camino_schema]); +export const file_camino_api = /*@__PURE__*/ fileDesc("ChBjYW1pbm8vYXBpLnByb3RvEgZjYW1pbm8iCwoJTnVsbFZhbHVlInwKC09iamVjdFZhbHVlEi8KBmZpZWxkcxgBIAMoCzIfLmNhbWluby5PYmplY3RWYWx1ZS5GaWVsZHNFbnRyeRo8CgtGaWVsZHNFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIioKCUxpc3RWYWx1ZRIdCgZ2YWx1ZXMYASADKAsyDS5jYW1pbm8uVmFsdWUiHQoIUmVmVmFsdWUSEQoJb2JqZWN0X2lkGAEgASgJIjwKCUNyZHRWYWx1ZRIMCgR0eXBlGAEgASgJEhAKCGVuY29kaW5nGAIgASgJEg8KB3BheWxvYWQYAyABKAwiqAEKEFN0YXRlVmFsdWVTb3VyY2USEQoJb2JqZWN0X2lkGAEgASgJEg8KB3Nsb3RfaWQYAiABKAkSFwoPdmFsdWVfdHlwZV9qc29uGAMgASgJEhsKE3N0b3JhZ2VfcG9saWN5X2pzb24YBCABKAkSEAoIcmV2aXNpb24YBSABKAQSKAoNY3JkdF9zbmFwc2hvdBgGIAEoCzIRLmNhbWluby5DcmR0VmFsdWUiNgoLVmFsdWVTb3VyY2USJwoFc3RhdGUYASABKAsyGC5jYW1pbm8uU3RhdGVWYWx1ZVNvdXJjZSL5AgoFVmFsdWUSJwoKbnVsbF92YWx1ZRgBIAEoCzIRLmNhbWluby5OdWxsVmFsdWVIABIUCgpib29sX3ZhbHVlGAIgASgISAASFgoMbnVtYmVyX3ZhbHVlGAMgASgBSAASFgoMc3RyaW5nX3ZhbHVlGAQgASgJSAASFwoNaW50ZWdlcl92YWx1ZRgFIAEoCUgAEhUKC2J5dGVzX3ZhbHVlGAYgASgMSAASKwoMb2JqZWN0X3ZhbHVlGAcgASgLMhMuY2FtaW5vLk9iamVjdFZhbHVlSAASJwoKbGlzdF92YWx1ZRgIIAEoCzIRLmNhbWluby5MaXN0VmFsdWVIABIlCglyZWZfdmFsdWUYCSABKAsyEC5jYW1pbm8uUmVmVmFsdWVIABInCgpjcmR0X3ZhbHVlGAogASgLMhEuY2FtaW5vLkNyZHRWYWx1ZUgAEiMKBnNvdXJjZRgLIAEoCzITLmNhbWluby5WYWx1ZVNvdXJjZUIGCgRraW5kIkYKHUluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0EiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIkcKHkluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXNwb25zZRIlCgRwbGFuGAEgASgLMhcuY2FtaW5vLlBlcnNpc3RlbmNlUGxhbiIbChlHZXRQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0IkMKGkdldFBlcnNpc3RlbmNlUGxhblJlc3BvbnNlEiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIrABChNDcmVhdGVPYmplY3RSZXF1ZXN0Eg8KB2F0b21faWQYASABKAkSRAoNaW5pdGlhbF9zdGF0ZRgCIAMoCzItLmNhbWluby5DcmVhdGVPYmplY3RSZXF1ZXN0LkluaXRpYWxTdGF0ZUVudHJ5GkIKEUluaXRpYWxTdGF0ZUVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPAoUQ3JlYXRlT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCIlChBHZXRPYmplY3RSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCSI5ChFHZXRPYmplY3RSZXNwb25zZRIkCgZvYmplY3QYASABKAsyFC5jYW1pbm8uQ2FtaW5vT2JqZWN0IiUKEkxpc3RPYmplY3RzUmVxdWVzdBIPCgdhdG9tX2lkGAEgASgJIjwKE0xpc3RPYmplY3RzUmVzcG9uc2USJQoHb2JqZWN0cxgBIAMoCzIULmNhbWluby5DYW1pbm9PYmplY3QiNgoQUmVhZFN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCSIxChFSZWFkU3RhdGVSZXNwb25zZRIcCgV2YWx1ZRgBIAEoCzINLmNhbWluby5WYWx1ZSJxChFXcml0ZVN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCRIcCgV2YWx1ZRgDIAEoCzINLmNhbWluby5WYWx1ZRIaChJjbGllbnRfbXV0YXRpb25faWQYBCABKAkiWAoSV3JpdGVTdGF0ZVJlc3BvbnNlEhwKBXZhbHVlGAEgASgLMg0uY2FtaW5vLlZhbHVlEiQKBm9iamVjdBgCIAEoCzIULmNhbWluby5DYW1pbm9PYmplY3QiwAEKEkNvbm5lY3RFZGdlUmVxdWVzdBIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCRIRCglvYmplY3RfaWQYAyABKAkSGAoQdGFyZ2V0X29iamVjdF9pZBgEIAEoCRIUCgdvcmRpbmFsGAUgASgFSACIAQESGwoOdGFyZ2V0X29yZGluYWwYBiABKAVIAYgBAUIKCghfb3JkaW5hbEIRCg9fdGFyZ2V0X29yZGluYWwiNwoTQ29ubmVjdEVkZ2VSZXNwb25zZRIgCgRlZGdlGAEgASgLMhIuY2FtaW5vLkNhbWlub0VkZ2UiVAoSUmVzb2x2ZUVkZ2VSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCRIUCgxlZGdlX3R5cGVfaWQYAiABKAkSFQoNcHJvamVjdGlvbl9pZBgDIAEoCSI4ChNSZXNvbHZlRWRnZVJlc3BvbnNlEiEKBWVkZ2VzGAEgAygLMhIuY2FtaW5vLkNhbWlub0VkZ2UiKAoVRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Eg8KB2VkZ2VfaWQYASABKAkiKQoWRGlzY29ubmVjdEVkZ2VSZXNwb25zZRIPCgdlZGdlX2lkGAEgASgJIlgKD0NvbGxlY3Rpb25FbnRyeRIPCgdlZGdlX2lkGAEgASgJEhgKEHRhcmdldF9vYmplY3RfaWQYAiABKAkSGgoDa2V5GAMgASgLMg0uY2FtaW5vLlZhbHVlIlQKFlJlYWRDb2xsZWN0aW9uUmVzcG9uc2USEAoIcmV2aXNpb24YASABKAQSKAoHZW50cmllcxgCIAMoCzIXLmNhbWluby5Db2xsZWN0aW9uRW50cnkinwEKGFJlcGxhY2VDb2xsZWN0aW9uUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSFAoMZWRnZV90eXBlX2lkGAIgASgJEhUKDXByb2plY3Rpb25faWQYAyABKAkSGQoRZXhwZWN0ZWRfcmV2aXNpb24YBCABKAQSKAoHZW50cmllcxgFIAMoCzIXLmNhbWluby5Db2xsZWN0aW9uRW50cnkiIwoOTGlzdE9wc1JlcXVlc3QSEQoJb2JqZWN0X2lkGAEgASgJIjAKD0xpc3RPcHNSZXNwb25zZRIdCgNvcHMYASADKAsyEC5jYW1pbm8uQ2FtaW5vT3AibgoSV2F0Y2hPYmplY3RSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCRITCgthZnRlcl9vcF9pZBgCIAEoCRIYChBpbmNsdWRlX3NuYXBzaG90GAMgASgIEhYKDmF0dGFjaG1lbnRfaWRzGAQgAygJImsKEFdhdGNoT2JqZWN0RXZlbnQSEQoJb2JqZWN0X2lkGAEgASgJEiYKCHNuYXBzaG90GAIgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdBIcCgJvcBgDIAEoCzIQLmNhbWluby5DYW1pbm9PcCLZAgoMQ2FtaW5vT2JqZWN0EgoKAmlkGAEgASgJEg8KB2F0b21faWQYAiABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAMgASgJEhIKCmNyZWF0ZWRfYXQYBCABKAkSEgoKdXBkYXRlZF9hdBgFIAEoCRIuCgVzdGF0ZRgGIAMoCzIfLmNhbWluby5DYW1pbm9PYmplY3QuU3RhdGVFbnRyeRJBCg9zdGF0ZV9yZXZpc2lvbnMYByADKAsyKC5jYW1pbm8uQ2FtaW5vT2JqZWN0LlN0YXRlUmV2aXNpb25zRW50cnkaOwoKU3RhdGVFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBGjUKE1N0YXRlUmV2aXNpb25zRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgEOgI4ASK/AgoKQ2FtaW5vRWRnZRIKCgJpZBgBIAEoCRIUCgxlZGdlX3R5cGVfaWQYAiABKAkSFwoPZmlyc3Rfb2JqZWN0X2lkGAMgASgJEhgKEHNlY29uZF9vYmplY3RfaWQYBCABKAkSGwoTZmlyc3RfcHJvamVjdGlvbl9pZBgFIAEoCRIcChRzZWNvbmRfcHJvamVjdGlvbl9pZBgGIAEoCRIaCg1maXJzdF9vcmRpbmFsGAcgASgFSACIAQESGwoOc2Vjb25kX29yZGluYWwYCCABKAVIAYgBARISCgpjcmVhdGVkX2F0GAkgASgJEhYKDmZpcnN0X2tleV9qc29uGAogASgJEhcKD3NlY29uZF9rZXlfanNvbhgLIAEoCUIQCg5fZmlyc3Rfb3JkaW5hbEIRCg9fc2Vjb25kX29yZGluYWwimQEKCENhbWlub09wEgoKAmlkGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIPCgdvcF9raW5kGAMgASgJEh4KB3BheWxvYWQYBCABKAsyDS5jYW1pbm8uVmFsdWUSDQoFYWN0b3IYBSABKAkSEgoKY3JlYXRlZF9hdBgGIAEoCRIaChJjbGllbnRfbXV0YXRpb25faWQYByABKAkyuggKDUNhbWlub1NlcnZpY2USZwoWSW5zdGFsbFBlcnNpc3RlbmNlUGxhbhIlLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVxdWVzdBomLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USWwoSR2V0UGVyc2lzdGVuY2VQbGFuEiEuY2FtaW5vLkdldFBlcnNpc3RlbmNlUGxhblJlcXVlc3QaIi5jYW1pbm8uR2V0UGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USSQoMQ3JlYXRlT2JqZWN0EhsuY2FtaW5vLkNyZWF0ZU9iamVjdFJlcXVlc3QaHC5jYW1pbm8uQ3JlYXRlT2JqZWN0UmVzcG9uc2USQAoJR2V0T2JqZWN0EhguY2FtaW5vLkdldE9iamVjdFJlcXVlc3QaGS5jYW1pbm8uR2V0T2JqZWN0UmVzcG9uc2USRgoLTGlzdE9iamVjdHMSGi5jYW1pbm8uTGlzdE9iamVjdHNSZXF1ZXN0GhsuY2FtaW5vLkxpc3RPYmplY3RzUmVzcG9uc2USQAoJUmVhZFN0YXRlEhguY2FtaW5vLlJlYWRTdGF0ZVJlcXVlc3QaGS5jYW1pbm8uUmVhZFN0YXRlUmVzcG9uc2USQwoKV3JpdGVTdGF0ZRIZLmNhbWluby5Xcml0ZVN0YXRlUmVxdWVzdBoaLmNhbWluby5Xcml0ZVN0YXRlUmVzcG9uc2USRgoLQ29ubmVjdEVkZ2USGi5jYW1pbm8uQ29ubmVjdEVkZ2VSZXF1ZXN0GhsuY2FtaW5vLkNvbm5lY3RFZGdlUmVzcG9uc2USRgoLUmVzb2x2ZUVkZ2USGi5jYW1pbm8uUmVzb2x2ZUVkZ2VSZXF1ZXN0GhsuY2FtaW5vLlJlc29sdmVFZGdlUmVzcG9uc2USTwoORGlzY29ubmVjdEVkZ2USHS5jYW1pbm8uRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Gh4uY2FtaW5vLkRpc2Nvbm5lY3RFZGdlUmVzcG9uc2USTAoOUmVhZENvbGxlY3Rpb24SGi5jYW1pbm8uUmVzb2x2ZUVkZ2VSZXF1ZXN0Gh4uY2FtaW5vLlJlYWRDb2xsZWN0aW9uUmVzcG9uc2USVQoRUmVwbGFjZUNvbGxlY3Rpb24SIC5jYW1pbm8uUmVwbGFjZUNvbGxlY3Rpb25SZXF1ZXN0Gh4uY2FtaW5vLlJlYWRDb2xsZWN0aW9uUmVzcG9uc2USOgoHTGlzdE9wcxIWLmNhbWluby5MaXN0T3BzUmVxdWVzdBoXLmNhbWluby5MaXN0T3BzUmVzcG9uc2USRQoLV2F0Y2hPYmplY3QSGi5jYW1pbm8uV2F0Y2hPYmplY3RSZXF1ZXN0GhguY2FtaW5vLldhdGNoT2JqZWN0RXZlbnQwAWIGcHJvdG8z", [file_camino_schema]); /** * Describes the message camino.NullValue. * Use `create(NullValueSchema)` to create a new message. @@ -147,41 +147,56 @@ export const DisconnectEdgeRequestSchema = /*@__PURE__*/ messageDesc(file_camino * Use `create(DisconnectEdgeResponseSchema)` to create a new message. */ export const DisconnectEdgeResponseSchema = /*@__PURE__*/ messageDesc(file_camino_api, 27); +/** + * Describes the message camino.CollectionEntry. + * Use `create(CollectionEntrySchema)` to create a new message. + */ +export const CollectionEntrySchema = /*@__PURE__*/ messageDesc(file_camino_api, 28); +/** + * Describes the message camino.ReadCollectionResponse. + * Use `create(ReadCollectionResponseSchema)` to create a new message. + */ +export const ReadCollectionResponseSchema = /*@__PURE__*/ messageDesc(file_camino_api, 29); +/** + * Describes the message camino.ReplaceCollectionRequest. + * Use `create(ReplaceCollectionRequestSchema)` to create a new message. + */ +export const ReplaceCollectionRequestSchema = /*@__PURE__*/ messageDesc(file_camino_api, 30); /** * Describes the message camino.ListOpsRequest. * Use `create(ListOpsRequestSchema)` to create a new message. */ -export const ListOpsRequestSchema = /*@__PURE__*/ messageDesc(file_camino_api, 28); +export const ListOpsRequestSchema = /*@__PURE__*/ messageDesc(file_camino_api, 31); /** * Describes the message camino.ListOpsResponse. * Use `create(ListOpsResponseSchema)` to create a new message. */ -export const ListOpsResponseSchema = /*@__PURE__*/ messageDesc(file_camino_api, 29); +export const ListOpsResponseSchema = /*@__PURE__*/ messageDesc(file_camino_api, 32); /** * Describes the message camino.WatchObjectRequest. * Use `create(WatchObjectRequestSchema)` to create a new message. */ -export const WatchObjectRequestSchema = /*@__PURE__*/ messageDesc(file_camino_api, 30); +export const WatchObjectRequestSchema = /*@__PURE__*/ messageDesc(file_camino_api, 33); /** * Describes the message camino.WatchObjectEvent. * Use `create(WatchObjectEventSchema)` to create a new message. */ -export const WatchObjectEventSchema = /*@__PURE__*/ messageDesc(file_camino_api, 31); +export const WatchObjectEventSchema = /*@__PURE__*/ messageDesc(file_camino_api, 34); /** * Describes the message camino.CaminoObject. * Use `create(CaminoObjectSchema)` to create a new message. */ -export const CaminoObjectSchema = /*@__PURE__*/ messageDesc(file_camino_api, 32); +export const CaminoObjectSchema = /*@__PURE__*/ messageDesc(file_camino_api, 35); /** * Describes the message camino.CaminoEdge. * Use `create(CaminoEdgeSchema)` to create a new message. */ -export const CaminoEdgeSchema = /*@__PURE__*/ messageDesc(file_camino_api, 33); +export const CaminoEdgeSchema = /*@__PURE__*/ messageDesc(file_camino_api, 36); /** * Describes the message camino.CaminoOp. * Use `create(CaminoOpSchema)` to create a new message. */ -export const CaminoOpSchema = /*@__PURE__*/ messageDesc(file_camino_api, 34); +export const CaminoOpSchema = /*@__PURE__*/ messageDesc(file_camino_api, 37); /** * @generated from service camino.CaminoService */ diff --git a/dist/camino/schema_pb.d.ts b/dist/camino/schema_pb.d.ts index 53182fd..8595d64 100644 --- a/dist/camino/schema_pb.d.ts +++ b/dist/camino/schema_pb.d.ts @@ -34,6 +34,10 @@ export type AtomConformance = Message<"camino.AtomConformance"> & { * @generated from field: string interface_revision_id = 2; */ interfaceRevisionId: string; + /** + * @generated from field: string conformance_id = 3; + */ + conformanceId: string; }; /** * Describes the message camino.AtomConformance. @@ -68,6 +72,10 @@ export type StateAttachment = Message<"camino.StateAttachment"> & { * @generated from field: string default_value_json = 6; */ defaultValueJson: string; + /** + * @generated from field: string owner_conformance_id = 7; + */ + ownerConformanceId: string; }; /** * Describes the message camino.StateAttachment. @@ -127,6 +135,28 @@ export type EdgeEndpoint = Message<"camino.EdgeEndpoint"> & { * @generated from field: bool ordered = 5; */ ordered: boolean; + /** + * Empty means restrict. Direction is the endpoint being deleted. + * + * @generated from field: string on_delete = 6; + */ + onDelete: string; + /** + * @generated from field: bool retain_other = 7; + */ + retainOther: boolean; + /** + * Empty for sets/lists, otherwise string, boolean, or int64 map keys. + * + * @generated from field: string key_type = 8; + */ + keyType: string; + /** + * Explicit read-only dependency injection traversal, not mutation authority. + * + * @generated from field: bool public_traversal = 9; + */ + publicTraversal: boolean; }; /** * Describes the message camino.EdgeEndpoint. @@ -153,6 +183,10 @@ export type EdgeAttachment = Message<"camino.EdgeAttachment"> & { * @generated from field: camino.EdgeEndpoint second = 4; */ second?: EdgeEndpoint | undefined; + /** + * @generated from field: string owner_conformance_id = 5; + */ + ownerConformanceId: string; }; /** * Describes the message camino.EdgeAttachment. diff --git a/dist/camino/schema_pb.d.ts.map b/dist/camino/schema_pb.d.ts.map index 1cba90b..699a14e 100644 --- a/dist/camino/schema_pb.d.ts.map +++ b/dist/camino/schema_pb.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"schema_pb.d.ts","sourceRoot":"","sources":["../../src/camino/schema_pb.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"schema_pb.d.ts","sourceRoot":"","sources":["../../src/camino/schema_pb.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/camino/schema_pb.js b/dist/camino/schema_pb.js index 1086ba3..dfee49a 100644 --- a/dist/camino/schema_pb.js +++ b/dist/camino/schema_pb.js @@ -1,11 +1,11 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file camino/schema.proto (package camino, syntax proto3) /* eslint-disable */ import { enumDesc, fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; /** * Describes the file camino/schema.proto. */ -export const file_camino_schema = /*@__PURE__*/ fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiQQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJIqQBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIqYBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCCKHAQoORWRnZUF0dGFjaG1lbnQSFAoMZWRnZV90eXBlX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRIjCgVmaXJzdBgDIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSJAoGc2Vjb25kGAQgASgLMhQuY2FtaW5vLkVkZ2VFbmRwb2ludCLsAQoPUGVyc2lzdGVuY2VQbGFuEhQKDHdvcmtzcGFjZV9pZBgBIAEoCRIdChV3b3Jrc3BhY2VfcmV2aXNpb25faWQYAiABKAkSJQoFYXRvbXMYAyADKAsyFi5jYW1pbm8uQXRvbURlZmluaXRpb24SLQoMY29uZm9ybWFuY2VzGAQgAygLMhcuY2FtaW5vLkF0b21Db25mb3JtYW5jZRInCgZzdGF0ZXMYBSADKAsyFy5jYW1pbm8uU3RhdGVBdHRhY2htZW50EiUKBWVkZ2VzGAYgAygLMhYuY2FtaW5vLkVkZ2VBdHRhY2htZW50KmgKC0NhcmRpbmFsaXR5EhsKF0NBUkRJTkFMSVRZX1VOU1BFQ0lGSUVEEAASEAoMT1BUSU9OQUxfT05FEAESDwoLRVhBQ1RMWV9PTkUQAhIICgRNQU5ZEAMSDwoLTUFOWV9VTklRVUUQBGIGcHJvdG8z"); +export const file_camino_schema = /*@__PURE__*/ fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiWQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhYKDmNvbmZvcm1hbmNlX2lkGAMgASgJIsIBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYByABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIvsBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCBIRCglvbl9kZWxldGUYBiABKAkSFAoMcmV0YWluX290aGVyGAcgASgIEhAKCGtleV90eXBlGAggASgJEhgKEHB1YmxpY190cmF2ZXJzYWwYCSABKAgipQEKDkVkZ2VBdHRhY2htZW50EhQKDGVkZ2VfdHlwZV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSIwoFZmlyc3QYAyABKAsyFC5jYW1pbm8uRWRnZUVuZHBvaW50EiQKBnNlY29uZBgEIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYBSABKAki7AEKD1BlcnNpc3RlbmNlUGxhbhIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEiUKBWF0b21zGAMgAygLMhYuY2FtaW5vLkF0b21EZWZpbml0aW9uEi0KDGNvbmZvcm1hbmNlcxgEIAMoCzIXLmNhbWluby5BdG9tQ29uZm9ybWFuY2USJwoGc3RhdGVzGAUgAygLMhcuY2FtaW5vLlN0YXRlQXR0YWNobWVudBIlCgVlZGdlcxgGIAMoCzIWLmNhbWluby5FZGdlQXR0YWNobWVudCpoCgtDYXJkaW5hbGl0eRIbChdDQVJESU5BTElUWV9VTlNQRUNJRklFRBAAEhAKDE9QVElPTkFMX09ORRABEg8KC0VYQUNUTFlfT05FEAISCAoETUFOWRADEg8KC01BTllfVU5JUVVFEARiBnByb3RvMw"); /** * Describes the message camino.AtomDefinition. * Use `create(AtomDefinitionSchema)` to create a new message. diff --git a/dist/index.d.ts b/dist/index.d.ts index 91bb2a1..cbd3426 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,5 +1,8 @@ import http from "node:http"; +import { type QxObjectRef } from "./references.js"; export * from "./bindings.js"; +export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js"; +export { createMigrationContext, migrationObjectId, serveMigration, type MigrationContext, type MigrationInput, type MigrationOutput, type MigrationEdge } from "./migration.js"; import { type Client, type ConnectRouter } from "@connectrpc/connect"; import { CaminoService, type Value } from "./camino/api_pb.js"; import { OrchestratorRuntime } from "./quixos/orch_pb.js"; @@ -15,9 +18,7 @@ export type RuntimeDependency = { attachmentId: string; projectionId: string; }; -export declare const objectRef: (objectId: string) => { - $quixosRef: string; -}; +export declare const objectRef: (reference: QxObjectRef) => QxObjectRef; export declare const liveValue: (value: Value) => { $quixosValue: Value; }; @@ -35,23 +36,37 @@ export type StatePort = { export type EdgePort = { edgeTypeId: string; projectionId: string; - resolve(): Promise; - connect(targetObjectId: string): Promise; - disconnect(targetObjectId: string): Promise; + resolve(): Promise; + connect(target: QxObjectRef): Promise; + disconnect(target: QxObjectRef): Promise; + collection(): Promise; + replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise; +}; +export type RelationshipEntry = { + edgeId?: string; + target: T; + key?: string | boolean | bigint; +}; +export type RelationshipCollection = { + revision: bigint; + entries: RelationshipEntry[]; }; export type InterfacePort = { - objectId: string; + objectId: QxObjectRef; interfaceRevisionId: string; invoke(operationId: string, input?: Record): Promise; live(operationId: string, input?: Record): Promise>; }; export type ConstructorPort = { atomId: string; - construct(input?: Record): Promise; + construct(input?: Record): Promise; }; export type RuntimePort = StatePort | EdgePort | InterfacePort | ConstructorPort; export type RuntimeContext = { - objectId: string; + /** Cooperative cancellation. Completion is acknowledged only after the handler returns. */ + signal?: AbortSignal; + openSession?: () => Promise; + objectId: QxObjectRef; input: Record; inputProto: Record; ports: ReadonlyMap; @@ -60,6 +75,16 @@ export type RuntimeContext = { interface(portId: string): InterfacePort; constructor(portId: string): ConstructorPort; }; +export type RuntimeSession = { + id: string; + run(work: (context: RuntimeContext) => Promise): Promise; + /** Close the external resource first, then close its host retention/session. */ + close(): Promise; +}; +export declare class RuntimeAuthorityError extends Error { + readonly retryable: boolean; + constructor(message: string); +} export declare const createRuntimeContext: (camino: CaminoClient, orch: OrchClient, request: RuntimeRequest) => RuntimeContext; export type RuntimeHandler = (context: RuntimeContext) => unknown | Promise; export type DerivedHandler = { diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map index 585d1f4..7768e9d 100644 --- a/dist/index.d.ts.map +++ b/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index b9c237a..248ec48 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,7 +1,12 @@ import http from "node:http"; +import { readFileSync } from "node:fs"; +import { createInvocationRegistry } from "./invocations.js"; +import { isObjectReference, referenceFromWire, referenceToWire, assertReferenceFree } from "./references.js"; export * from "./bindings.js"; +export { relationshipMap, relationshipList, relationshipSet } from "./relationships.js"; import { AsyncLocalStorage } from "node:async_hooks"; -import { randomUUID } from "node:crypto"; +import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto"; +export { createMigrationContext, migrationObjectId, serveMigration } from "./migration.js"; import { create, equals } from "@bufbuild/protobuf"; import { Code, ConnectError, createClient } from "@connectrpc/connect"; import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node"; @@ -24,9 +29,11 @@ const base64ToBytes = (value) => Buffer.from(value, "base64"); const isRecord = (value) => Boolean(value) && typeof value === "object" && !Array.isArray(value); const isWrappedValue = (value) => isRecord(value) && "$quixosValue" in value && isRecord(value.$quixosValue) && value.$quixosValue.$typeName === "camino.Value"; -export const objectRef = (objectId) => ({ $quixosRef: objectId }); +export const objectRef = (reference) => { referenceToWire(reference); return reference; }; export const liveValue = (value) => ({ $quixosValue: value }); export const jsToProtoValue = (value) => { + if (isObjectReference(value)) + return create(ValueSchema, { kind: { case: "refValue", value: create(RefValueSchema, { objectId: referenceToWire(value) }) } }); if (isWrappedValue(value)) return value.$quixosValue; if (value === null || value === undefined) { @@ -47,11 +54,8 @@ export const jsToProtoValue = (value) => { kind: { case: "listValue", value: create(ListValueSchema, { values: value.map(jsToProtoValue) }) }, }); } - if (isRecord(value) && typeof value.$quixosRef === "string") { - return create(ValueSchema, { - kind: { case: "refValue", value: create(RefValueSchema, { objectId: value.$quixosRef }) }, - }); - } + if (isRecord(value) && "$quixosRef" in value) + throw new Error("Raw ID wrappers are not object references"); if (isRecord(value) && typeof value.$quixosCrdtType === "string" && typeof value.$quixosCrdtPayload === "string") { return create(ValueSchema, { @@ -79,7 +83,7 @@ export const protoValueToJs = (value) => { case "stringValue": case "integerValue": return value.kind.value; case "bytesValue": return bytesToBase64(value.kind.value); - case "refValue": return value.kind.value.objectId; + case "refValue": return referenceFromWire(value.kind.value.objectId); case "listValue": return value.kind.value.values.map(protoValueToJs); case "objectValue": return Object.fromEntries(Object.entries(value.kind.value.fields).map(([key, entry]) => [key, protoValueToJs(entry)])); case "crdtValue": return { @@ -90,6 +94,10 @@ export const protoValueToJs = (value) => { } }; export const protoFieldsToJs = (fields) => Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, protoValueToJs(value)])); +export class RuntimeAuthorityError extends Error { + retryable; + constructor(message) { super(message); this.name = "RuntimeAuthorityError"; this.retryable = /WORKSPACE_FENCED|STALE_EPOCH/.test(message); } +} const targetForEdge = (edge, projectionId) => edge.firstProjectionId === projectionId ? edge.secondObjectId : edge.firstObjectId; export const createRuntimeContext = (camino, orch, request) => { const ports = new Map(); @@ -112,6 +120,7 @@ export const createRuntimeContext = (camino, orch, request) => { return liveValue(value.value); }, async set(value) { + assertReferenceFree(isWrappedValue(value) ? protoValueToJs(value.$quixosValue) : value); await camino.writeState({ objectId: dependencyObjectId, slotId, value: jsToProtoValue(value) }); }, }; @@ -121,18 +130,34 @@ export const createRuntimeContext = (camino, orch, request) => { case "edge": { const { edgeTypeId, projectionId } = dependency.binding.value; const dependencyObjectId = dependency.objectId || request.objectId; + const collectionResult = (response) => ({ revision: response.revision, + entries: response.entries.map((entry) => ({ edgeId: entry.edgeId, target: referenceFromWire(entry.targetObjectId), + ...(entry.key ? { key: entry.key.kind.case === "integerValue" ? BigInt(entry.key.kind.value) : protoValueToJs(entry.key) } : {}) })) }); const edge = { edgeTypeId, projectionId, + async collection() { + await recordDependency({ kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId }); + return collectionResult(await camino.readCollection({ objectId: dependencyObjectId, edgeTypeId, projectionId })); + }, + async replace(entries, expectedRevision) { + return collectionResult(await camino.replaceCollection({ objectId: dependencyObjectId, edgeTypeId, projectionId, expectedRevision, + entries: entries.map((entry) => { + assertReferenceFree(entry.key); + return { edgeId: entry.edgeId ?? "", targetObjectId: referenceToWire(entry.target), key: entry.key === undefined ? undefined : jsToProtoValue(entry.key) }; + }) })); + }, async resolve() { await recordDependency({ kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId }); const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId }); - return result.edges.map((entry) => targetForEdge(entry, projectionId)); + return result.edges.map((entry) => referenceFromWire(targetForEdge(entry, projectionId))); }, - async connect(targetObjectId) { + async connect(target) { + const targetObjectId = referenceToWire(target); await camino.connectEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId, targetObjectId }); }, - async disconnect(targetObjectId) { + async disconnect(target) { + const targetObjectId = referenceToWire(target); const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId }); for (const entry of result.edges) { if (targetForEdge(entry, projectionId) === targetObjectId) @@ -174,7 +199,7 @@ export const createRuntimeContext = (camino, orch, request) => { return response.result; }; const capability = { - objectId: dependencyObjectId, + objectId: referenceFromWire(dependencyObjectId), interfaceRevisionId, async invoke(operationId, input = {}) { return protoValueToJs(await invoke(operationId, input)); @@ -200,7 +225,7 @@ export const createRuntimeContext = (camino, orch, request) => { }); if (!response.object) throw new Error(`Constructor ${atomId} returned no object`); - return response.object.id; + return referenceFromWire(response.object.id); }, }; ports.set(dependency.portId, constructor); @@ -214,7 +239,7 @@ export const createRuntimeContext = (camino, orch, request) => { return port; }; return { - objectId: request.objectId, + objectId: referenceFromWire(request.objectId), input: protoFieldsToJs(request.input), inputProto: request.input, ports, @@ -238,9 +263,12 @@ const protoDependencies = (dependencies) => dependencies.map((entry) => create(D projectionId: entry.kind === "edge" ? entry.projectionId : "", })); export const createPackageRuntimeRoutes = (config) => { + const invocations = createInvocationRegistry(); const headers = {}; - if (process.env.CAMINO_RUNTIME_AUTH_TOKEN) { - headers["x-camino-runtime-token"] = process.env.CAMINO_RUNTIME_AUTH_TOKEN; + const processToken = process.env.CAMINO_RUNTIME_AUTH_TOKEN ?? (process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE + ? readFileSync(process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE, "utf8").trim() : ""); + if (processToken) { + headers["x-camino-runtime-token"] = processToken; } else if (process.env.CAMINO_RUNTIME_AUTH_REQUIRED === "1") { throw new Error("CAMINO_RUNTIME_AUTH_TOKEN is required"); @@ -259,19 +287,115 @@ export const createPackageRuntimeRoutes = (config) => { baseUrl: config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311", httpVersion: "1.1", })); + const authenticateInstance = (header) => { + if (!process.env.QUIXOS_RUNTIME_INSTANCE_ID) + return; // standalone development ABI + const supplied = Buffer.from(header.get("x-quixos-instance-token") ?? ""); + const expected = Buffer.from(processToken); + if (!expected.length || supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) { + throw new ConnectError("Invalid runtime instance credential", Code.Unauthenticated); + } + }; + const clientsFor = (request) => { + const context = request.context; + if (process.env.QUIXOS_RUNTIME_INSTANCE_ID && (!context?.grant || context.instanceId !== process.env.QUIXOS_RUNTIME_INSTANCE_ID || !context.workspaceEpoch)) { + throw new ConnectError("Managed invocation requires an exact instance and epoch grant", Code.Unauthenticated); + } + if (!context?.grant) + return { camino, orch }; + const transport = (url) => createConnectTransport({ baseUrl: url, httpVersion: "1.1", interceptors: [(next) => async (call) => { + call.header.set("x-quixos-invocation-grant", context.grant); + call.header.set("x-camino-runtime-token", processToken); + return next(call); + }] }); + return { + camino: createClient(CaminoService, transport(config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310")), + orch: createClient(OrchestratorRuntime, transport(config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311")), + }; + }; + const runtimeControl = async (operation, input) => { + const response = await fetch(`${config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310"}/__runtime/${operation}`, { + method: "POST", headers: { "content-type": "application/json", "x-camino-runtime-token": processToken }, body: JSON.stringify(input), signal: AbortSignal.timeout(10_000), + }); + const value = await response.json(); + if (!response.ok) + throw new RuntimeAuthorityError(value.error ?? "Runtime authority request failed"); + return value; + }; + const attachSessions = (runtimeContext, request) => { + if (!request.context?.grant || !request.context.ownerConformanceId) + return; + runtimeContext.openSession = async () => { + const ownerId = request.context.ownerConformanceId; + const registration = { grant: request.context.grant, objectId: request.objectId, ownerId, + sessionId: `session:${randomBytes(16).toString("hex")}`, token: randomBytes(32).toString("base64url") }; + const register = () => runtimeControl("register-session", registration); + const registered = await register().catch((error) => { + // Retry a transport/lost-response failure with exactly the same identity. + // Admission/authority errors are definitive and must not be retried here. + if (error instanceof RuntimeAuthorityError) + throw error; + return register(); + }); + let closed = false; + return { + id: registered.sessionId, + async run(work) { + if (closed) + throw new RuntimeAuthorityError("SESSION_CLOSED"); + // Acquisition happens before user code. A fence failure can be retried + // by the caller without replaying a side-effecting callback. + const grant = await runtimeControl("acquire-session", registered); + const execution = invocations.begin(grant.invocationId); + const sessionRequest = { ...request, context: { grant: grant.grant, instanceId: grant.instanceId, workspaceEpoch: grant.epoch } }; + const clients = clientsFor(sessionRequest); + const context = createRuntimeContext(clients.camino, clients.orch, sessionRequest); + context.signal = execution.signal; + try { + return await work(context); + } + finally { + execution.finish(); + await runtimeControl("complete-invocation", { invocationId: grant.invocationId }).catch((error) => console.error("Session completion will be reconciled by the host", error)); + } + }, + async close() { await runtimeControl("close-session", registered); closed = true; }, + }; + }; + }; return (router) => router.service(PackageRuntime, { - handshake: () => create(HandshakeResponseSchema, { + handshake: (request) => create(HandshakeResponseSchema, { packageRevisionId: config.packageRevisionId, runtimeProtocolVersion: "quixos-capabilities-v1", exportIds: Object.keys(config.exports), + capabilities: ["invocation-completion-v1", "instance-authentication-v1", "epoch-grants-v1"], + instanceId: process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "", + authenticationProof: request.nonce && processToken ? createHmac("sha256", processToken) + .update(JSON.stringify([request.nonce, process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "", config.packageRevisionId])) + .digest("hex") : "", }), - invoke: async (request) => { + getInvocationStatus: (request, context) => { + authenticateInstance(context.requestHeader); + return invocations.status(request.invocationId); + }, + cancelInvocation: (request, context) => { + authenticateInstance(context.requestHeader); + return invocations.cancel(request.invocationId); + }, + invoke: async (request, context) => { + authenticateInstance(context.requestHeader); + const { camino, orch } = clientsFor(request); const exportId = request.export?.exportId; const handler = exportId ? config.exports[exportId] : undefined; if (!handler) throw new ConnectError(`Unknown export ${exportId ?? ""}`, Code.NotFound); + const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID())); try { - const result = await evaluate(handler, createRuntimeContext(camino, orch, request)); + const runtimeContext = createRuntimeContext(camino, orch, request); + attachSessions(runtimeContext, request); + runtimeContext.signal = AbortSignal.any([context.signal, execution.signal]); + const result = await evaluate(handler, runtimeContext); + execution.finish(); return create(InvokeResponseSchema, { ok: true, result: result.value, @@ -279,6 +403,7 @@ export const createPackageRuntimeRoutes = (config) => { }); } catch (error) { + execution.finish(true); return create(InvokeResponseSchema, { ok: false, error: error instanceof Error ? error.message : String(error), @@ -286,130 +411,141 @@ export const createPackageRuntimeRoutes = (config) => { } }, watch: async function* (request, context) { + authenticateInstance(context.requestHeader); + const { camino, orch } = clientsFor(request); const exportId = request.export?.exportId; const handler = exportId ? config.exports[exportId] : undefined; if (!handler || !isDerived(handler)) { throw new ConnectError(`Export ${exportId ?? ""} is not derived`, Code.FailedPrecondition); } - const watchId = `watch:${randomUUID()}`; - const runtimeContext = createRuntimeContext(camino, orch, request); - const subscriptions = new Map(); - const establishing = new Map(); - let subscriptionEpoch = 0; - const ensureSubscription = async (dependency) => { - const key = dependencyKey(dependency); - if (subscriptions.has(key)) - return; - const pending = establishing.get(key); - if (pending) - return await pending; - const establish = (async () => { - const controller = new AbortController(); - const stream = camino.watchObject({ objectId: dependency.objectId, includeSnapshot: true }, { signal: controller.signal })[Symbol.asyncIterator](); + const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID())); + const signal = AbortSignal.any([context.signal, execution.signal]); + try { + const watchId = `watch:${randomUUID()}`; + const runtimeContext = createRuntimeContext(camino, orch, request); + attachSessions(runtimeContext, request); + runtimeContext.signal = signal; + const subscriptions = new Map(); + const establishing = new Map(); + let subscriptionEpoch = 0; + const ensureSubscription = async (dependency) => { + const key = dependencyKey(dependency); + if (subscriptions.has(key)) + return; + const pending = establishing.get(key); + if (pending) + return await pending; + const establish = (async () => { + const controller = new AbortController(); + const stream = camino.watchObject({ objectId: dependency.objectId, includeSnapshot: true, attachmentIds: request.context?.grant ? [dependency.attachmentId] : [] }, { signal: controller.signal })[Symbol.asyncIterator](); + try { + // Camino subscribes before producing the snapshot, so once this + // resolves the following state/edge read cannot race the stream. + const snapshot = await stream.next(); + if (snapshot.done) + throw new Error(`Dependency stream ${key} ended during setup`); + const waitNext = () => stream.next().then((result) => ({ key, done: Boolean(result.done) }), (error) => ({ key, done: true, error })); + const subscription = { + dependency, + controller, + waitNext, + next: Promise.resolve({ key, done: false }), + }; + subscription.next = waitNext(); + subscriptions.set(key, subscription); + subscriptionEpoch += 1; + } + catch (error) { + controller.abort(); + throw error; + } + })(); + establishing.set(key, establish); try { - // Camino subscribes before producing the snapshot, so once this - // resolves the following state/edge read cannot race the stream. - const snapshot = await stream.next(); - if (snapshot.done) - throw new Error(`Dependency stream ${key} ended during setup`); - const waitNext = () => stream.next().then((result) => ({ key, done: Boolean(result.done) }), (error) => ({ key, done: true, error })); - const subscription = { - dependency, - controller, - waitNext, - next: Promise.resolve({ key, done: false }), - }; - subscription.next = waitNext(); - subscriptions.set(key, subscription); - subscriptionEpoch += 1; + await establish; } - catch (error) { - controller.abort(); - throw error; + finally { + establishing.delete(key); } - })(); - establishing.set(key, establish); + }; + const abortAll = () => { + for (const subscription of subscriptions.values()) { + subscription.controller.abort(); + } + }; + signal.addEventListener("abort", abortAll, { once: true }); + const evaluateWithStableSubscriptions = async () => { + // A direct state/edge port records its dependency before reading it, + // but a nested interface invocation can only report its transitive + // dependencies after that invocation returns. Once a new dependency + // stream is established, evaluate again so every read contributing to + // the emitted value happened after its stream became live. + for (let pass = 0; pass < 32; pass += 1) { + const before = subscriptionEpoch; + const result = await evaluate(handler, runtimeContext, ensureSubscription); + if (subscriptionEpoch === before) + return result; + } + throw new Error("Derived dependency discovery did not stabilize after 32 passes"); + }; try { - await establish; + let current = await evaluateWithStableSubscriptions(); + yield create(WatchEventSchema, { + watchId, + value: current.value, + dependencies: protoDependencies(current.dependencies), + initial: true, + }); + const abort = new Promise((resolve) => { + if (signal.aborted) + resolve("abort"); + else + signal.addEventListener("abort", () => resolve("abort"), { once: true }); + }); + while (!signal.aborted) { + if (subscriptions.size === 0) { + await abort; + break; + } + const outcome = await Promise.race([ + ...[...subscriptions.values()].map((entry) => entry.next), + abort, + ]); + if (outcome === "abort") + break; + const subscription = subscriptions.get(outcome.key); + if (!subscription) + continue; + if (outcome.error) + throw outcome.error; + if (outcome.done) + throw new Error(`Dependency stream ${outcome.key} ended unexpectedly`); + subscription.next = subscription.waitNext(); + const updated = await evaluateWithStableSubscriptions(); + const active = new Set(updated.dependencies.map(dependencyKey)); + for (const [key, entry] of subscriptions) { + if (!active.has(key)) { + entry.controller.abort(); + subscriptions.delete(key); + } + } + if (!equals(ValueSchema, current.value, updated.value)) { + yield create(WatchEventSchema, { + watchId, + value: updated.value, + dependencies: protoDependencies(updated.dependencies), + }); + } + current = updated; + } } finally { - establishing.delete(key); - } - }; - const abortAll = () => { - for (const subscription of subscriptions.values()) { - subscription.controller.abort(); - } - }; - context.signal.addEventListener("abort", abortAll, { once: true }); - const evaluateWithStableSubscriptions = async () => { - // A direct state/edge port records its dependency before reading it, - // but a nested interface invocation can only report its transitive - // dependencies after that invocation returns. Once a new dependency - // stream is established, evaluate again so every read contributing to - // the emitted value happened after its stream became live. - for (let pass = 0; pass < 32; pass += 1) { - const before = subscriptionEpoch; - const result = await evaluate(handler, runtimeContext, ensureSubscription); - if (subscriptionEpoch === before) - return result; - } - throw new Error("Derived dependency discovery did not stabilize after 32 passes"); - }; - let current = await evaluateWithStableSubscriptions(); - yield create(WatchEventSchema, { - watchId, - value: current.value, - dependencies: protoDependencies(current.dependencies), - initial: true, - }); - const abort = new Promise((resolve) => { - if (context.signal.aborted) - resolve("abort"); - else - context.signal.addEventListener("abort", () => resolve("abort"), { once: true }); - }); - try { - while (!context.signal.aborted) { - if (subscriptions.size === 0) { - await abort; - break; - } - const outcome = await Promise.race([ - ...[...subscriptions.values()].map((entry) => entry.next), - abort, - ]); - if (outcome === "abort") - break; - const subscription = subscriptions.get(outcome.key); - if (!subscription) - continue; - if (outcome.error) - throw outcome.error; - if (outcome.done) - throw new Error(`Dependency stream ${outcome.key} ended unexpectedly`); - subscription.next = subscription.waitNext(); - const updated = await evaluateWithStableSubscriptions(); - const active = new Set(updated.dependencies.map(dependencyKey)); - for (const [key, entry] of subscriptions) { - if (!active.has(key)) { - entry.controller.abort(); - subscriptions.delete(key); - } - } - if (!equals(ValueSchema, current.value, updated.value)) { - yield create(WatchEventSchema, { - watchId, - value: updated.value, - dependencies: protoDependencies(updated.dependencies), - }); - } - current = updated; + signal.removeEventListener("abort", abortAll); + abortAll(); } } finally { - context.signal.removeEventListener("abort", abortAll); - abortAll(); + execution.finish(); } }, }); diff --git a/dist/invocations.d.ts b/dist/invocations.d.ts new file mode 100644 index 0000000..d450d24 --- /dev/null +++ b/dist/invocations.d.ts @@ -0,0 +1,16 @@ +/** Execution completion, not HTTP disconnection, is the drain boundary. */ +export declare const createInvocationRegistry: () => { + begin(id: string): { + signal: AbortSignal; + finish(failed?: boolean): void; + }; + status(id: string): { + invocationId: string; + state: string; + }; + cancel(id: string): { + invocationId: string; + state: string; + }; +}; +//# sourceMappingURL=invocations.d.ts.map \ No newline at end of file diff --git a/dist/invocations.d.ts.map b/dist/invocations.d.ts.map new file mode 100644 index 0000000..e8eaf0d --- /dev/null +++ b/dist/invocations.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"invocations.d.ts","sourceRoot":"","sources":["../src/invocations.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,eAAO,MAAM,wBAAwB;IAGjC,KAAK,KAAK,MAAM;QAOL,MAAM;QAA2B,MAAM;;IAElD,MAAM,KAAK,MAAM;QAAa,YAAY;QAAM,KAAK;;IACrD,MAAM,KAAK,MAAM;;;;CASpB,CAAC"} \ No newline at end of file diff --git a/dist/invocations.js b/dist/invocations.js new file mode 100644 index 0000000..25280b9 --- /dev/null +++ b/dist/invocations.js @@ -0,0 +1,26 @@ +/** Execution completion, not HTTP disconnection, is the drain boundary. */ +export const createInvocationRegistry = () => { + const entries = new Map(); + return { + begin(id) { + if (!id || entries.has(id)) + throw new Error("Invocation ID is missing or already used; invocations are never replayed implicitly"); + // Completed identities remain until process retirement. A bounded process + // may reject new work; it must not evict and accidentally replay a call. + if (entries.size >= 100_000) + throw new Error("Invocation registry full; explicit runtime retirement required"); + const entry = { state: "running", controller: new AbortController() }; + entries.set(id, entry); + return { signal: entry.controller.signal, finish(failed = false) { entry.state = failed ? "failed" : "completed"; } }; + }, + status(id) { return { invocationId: id, state: entries.get(id)?.state ?? "unknown" }; }, + cancel(id) { + const entry = entries.get(id); + if (entry && ["running", "cancellation-requested"].includes(entry.state)) { + entry.state = "cancellation-requested"; + entry.controller.abort(); + } + return this.status(id); + }, + }; +}; diff --git a/dist/migration.d.ts b/dist/migration.d.ts new file mode 100644 index 0000000..40b87cb --- /dev/null +++ b/dist/migration.d.ts @@ -0,0 +1,72 @@ +export type MigrationInput = { + schemaVersion: 1; + executionId: string; + exportId: string; + ports: { + name: string; + binding: string; + view: "old" | "new"; + access: ("read" | "write" | "create" | "edge")[]; + atomId?: string; + attachedAtomId?: string; + defaultValue?: unknown; + states?: { + objectId: string; + value: unknown; + }[]; + edges?: MigrationEdge[]; + }[]; +}; +export type MigrationEdge = { + id: string; + edgeTypeId: string; + firstObjectId: string; + secondObjectId: string; + firstProjectionId: string; + secondProjectionId: string; + firstOrdinal?: number; + secondOrdinal?: number; + firstKeyJson?: string; + secondKeyJson?: string; +}; +export type MigrationOutput = { + schemaVersion: 1; + executionId: string; + writes: { + port: string; + objectId: string; + value: unknown; + }[]; + creates: { + port: string; + logicalKey: string; + objectId: string; + }[]; + edgeReplacements: { + port: string; + edges: MigrationEdge[]; + }[]; +}; +export type MigrationContext = { + enumerate(port: string): { + objectId: string; + value: unknown; + }[]; + read(port: string, objectId: string): unknown; + write(port: string, objectId: string, value: unknown): void; + create(port: string, logicalKey: string): string; + edges(port: string): MigrationEdge[]; + replaceEdges(port: string, edges: MigrationEdge[]): void; +}; +export declare const migrationObjectId: (executionId: string, port: string, logicalKey: string) => string; +/** No ordinary RuntimeContext or network/database clients are supplied here. + * Process isolation belongs to the host, not this convenience API. */ +export declare const createMigrationContext: (input: MigrationInput) => { + context: MigrationContext; + result: () => MigrationOutput; +}; +/** Entrypoint for an immutable package's dedicated bin/migrate executable. + * stdout is protocol-only; send diagnostics to stderr. The host independently + * validates every write, helper identity, contract, and completion receipt. */ +export declare const serveMigration: (exports: Record void | Promise>) => Promise; +//# sourceMappingURL=migration.d.ts.map \ No newline at end of file diff --git a/dist/migration.d.ts.map b/dist/migration.d.ts.map new file mode 100644 index 0000000..e003bdd --- /dev/null +++ b/dist/migration.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../src/migration.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IACxD,KAAK,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,KAAK,GAAG,KAAK,CAAC;QAAC,MAAM,EAAE,CAAC,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAC5H,cAAc,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,OAAO,CAAC;QAChD,MAAM,CAAC,EAAE;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,OAAO,CAAA;SAAC,EAAE,CAAC;QAAC,KAAK,CAAC,EAAE,aAAa,EAAE,CAAA;KAAC,EAAE,CAAC;CAC7E,CAAC;AACF,MAAM,MAAM,aAAa,GAAG;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAC,CAAC;AACjQ,MAAM,MAAM,eAAe,GAAG;IAAC,aAAa,EAAE,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IACnE,MAAM,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,EAAE,CAAC;IAC3D,OAAO,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,EAAE,CAAC;IAChE,gBAAgB,EAAE;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,aAAa,EAAE,CAAA;KAAC,EAAE,CAAA;CAAC,CAAC;AAC9D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAC,EAAE,CAAC;IAC9D,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9C,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5D,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;IACjD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAAC;IACrC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;CAC1D,CAAC;AACF,eAAO,MAAM,iBAAiB,gBAAiB,MAAM,QAAQ,MAAM,cAAc,MAAM,WACwB,CAAC;AAEhH;sEACsE;AACtE,eAAO,MAAM,sBAAsB,UAAW,cAAc;;;CAgD3D,CAAC;AAEF;;+EAE+E;AAC/E,eAAO,MAAM,cAAc,YAAmB,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,kBAehH,CAAC"} \ No newline at end of file diff --git a/dist/migration.js b/dist/migration.js new file mode 100644 index 0000000..5bf1173 --- /dev/null +++ b/dist/migration.js @@ -0,0 +1,93 @@ +import { createHash } from "node:crypto"; +export const migrationObjectId = (executionId, port, logicalKey) => `obj:migration:${createHash("sha256").update(JSON.stringify([executionId, port, logicalKey])).digest("hex")}`; +/** No ordinary RuntimeContext or network/database clients are supplied here. + * Process isolation belongs to the host, not this convenience API. */ +export const createMigrationContext = (input) => { + if (input.schemaVersion !== 1 || !input.executionId || new Set(input.ports.map((entry) => entry.name)).size !== input.ports.length) + throw new Error("Invalid migration input"); + const output = { schemaVersion: 1, executionId: input.executionId, writes: [], creates: [], edgeReplacements: [] }; + const port = (name, access) => { + const selected = input.ports.find((entry) => entry.name === name); + if (!selected?.access.includes(access) || (selected.view === "old" && access !== "read")) + throw new Error(`Migration port ${name} does not grant ${access}`); + return selected; + }; + const context = { + enumerate(name) { + const selected = port(name, "read"), states = structuredClone(selected.states ?? []); + if (selected.view === "new" && Object.hasOwn(selected, "defaultValue")) + for (const helper of output.creates) { + if (input.ports.find((entry) => entry.name === helper.port)?.atomId === selected.attachedAtomId && !states.some((entry) => entry.objectId === helper.objectId)) + states.push({ objectId: helper.objectId, value: structuredClone(selected.defaultValue) }); + } + if (selected.view === "new") + for (const write of output.writes) { + if (input.ports.find((entry) => entry.name === write.port)?.binding !== selected.binding) + continue; + const existing = states.findIndex((entry) => entry.objectId === write.objectId), entry = { objectId: write.objectId, value: structuredClone(write.value) }; + if (existing < 0) + states.push(entry); + else + states[existing] = entry; + } + return states.sort((a, b) => a.objectId < b.objectId ? -1 : a.objectId > b.objectId ? 1 : 0); + }, + read(name, objectId) { return context.enumerate(name).find((entry) => entry.objectId === objectId)?.value; }, + write(name, objectId, value) { + port(name, "write"); + const previous = output.writes.findIndex((entry) => entry.port === name && entry.objectId === objectId); + const entry = { port: name, objectId, value: structuredClone(value) }; + if (previous < 0) + output.writes.push(entry); + else + output.writes[previous] = entry; + }, + create(name, logicalKey) { + port(name, "create"); + if (!logicalKey || logicalKey.length > 1024) + throw new Error("Migration creation requires a bounded stable logical key"); + const objectId = migrationObjectId(input.executionId, name, logicalKey); + if (!output.creates.some((entry) => entry.objectId === objectId)) + output.creates.push({ port: name, logicalKey, objectId }); + return objectId; + }, + edges(name) { + const selected = port(name, "read"); + const replacement = selected.view === "new" ? output.edgeReplacements.find((entry) => input.ports.find((candidate) => candidate.name === entry.port)?.binding === selected.binding) : undefined; + return structuredClone(replacement?.edges ?? selected.edges ?? []); + }, + replaceEdges(name, edges) { + port(name, "edge"); + const previous = output.edgeReplacements.findIndex((entry) => entry.port === name); + const entry = { port: name, edges: structuredClone(edges) }; + if (previous < 0) + output.edgeReplacements.push(entry); + else + output.edgeReplacements[previous] = entry; + }, + }; + return { context, result: () => structuredClone(output) }; +}; +/** Entrypoint for an immutable package's dedicated bin/migrate executable. + * stdout is protocol-only; send diagnostics to stderr. The host independently + * validates every write, helper identity, contract, and completion receipt. */ +export const serveMigration = async (exports) => { + const chunks = []; + let bytes = 0; + for await (const chunk of process.stdin) { + bytes += chunk.length; + if (bytes > 16 * 1024 * 1024) + throw new Error("Migration input exceeds 16 MiB"); + chunks.push(Buffer.from(chunk)); + } + const input = JSON.parse(Buffer.concat(chunks).toString("utf8")); + const implementation = Object.hasOwn(exports, input.exportId) ? exports[input.exportId] : undefined; + if (!implementation) + throw new Error("Unknown migration export"); + const execution = createMigrationContext(input); + await implementation(execution.context); + const result = JSON.stringify(execution.result()); + if (Buffer.byteLength(result) > 16 * 1024 * 1024) + throw new Error("Migration output exceeds 16 MiB"); + process.stdout.write(`${result}\n`); +}; diff --git a/dist/quixos/orch_pb.js b/dist/quixos/orch_pb.js index 6506a0a..2b60b12 100644 --- a/dist/quixos/orch_pb.js +++ b/dist/quixos/orch_pb.js @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/orch.proto (package quixos.orch, syntax proto3) /* eslint-disable */ import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; diff --git a/dist/quixos/package_pb.js b/dist/quixos/package_pb.js index 0055a09..4b14ab8 100644 --- a/dist/quixos/package_pb.js +++ b/dist/quixos/package_pb.js @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/package.proto (package quixos, syntax proto3) /* eslint-disable */ import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; diff --git a/dist/quixos/refs_pb.js b/dist/quixos/refs_pb.js index 0223ff5..e205665 100644 --- a/dist/quixos/refs_pb.js +++ b/dist/quixos/refs_pb.js @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/refs.proto (package quixos, syntax proto3) /* eslint-disable */ import { fileDesc, messageDesc } from "@bufbuild/protobuf/codegenv2"; diff --git a/dist/quixos/runtime_pb.d.ts b/dist/quixos/runtime_pb.d.ts index e3ba60d..575eea5 100644 --- a/dist/quixos/runtime_pb.d.ts +++ b/dist/quixos/runtime_pb.d.ts @@ -14,6 +14,10 @@ export type HandshakeRequest = Message<"quixos.runtime.HandshakeRequest"> & { * @generated from field: string orch_protocol_version = 1; */ orchProtocolVersion: string; + /** + * @generated from field: string nonce = 2; + */ + nonce: string; }; /** * Describes the message quixos.runtime.HandshakeRequest. @@ -36,12 +40,94 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & { * @generated from field: repeated string export_ids = 3; */ exportIds: string[]; + /** + * @generated from field: string instance_id = 4; + */ + instanceId: string; + /** + * @generated from field: string authentication_proof = 5; + */ + authenticationProof: string; + /** + * @generated from field: repeated string capabilities = 6; + */ + capabilities: string[]; }; /** * Describes the message quixos.runtime.HandshakeResponse. * Use `create(HandshakeResponseSchema)` to create a new message. */ export declare const HandshakeResponseSchema: GenMessage; +/** + * @generated from message quixos.runtime.InvocationContext + */ +export type InvocationContext = Message<"quixos.runtime.InvocationContext"> & { + /** + * @generated from field: string workspace_epoch = 1; + */ + workspaceEpoch: string; + /** + * @generated from field: string instance_id = 2; + */ + instanceId: string; + /** + * @generated from field: string binding_digest = 3; + */ + bindingDigest: string; + /** + * @generated from field: string grant = 4; + */ + grant: string; + /** + * @generated from field: string session_id = 5; + */ + sessionId: string; + /** + * Host-selected owner; packages must not invent workspace-local ownership. + * + * @generated from field: string owner_conformance_id = 6; + */ + ownerConformanceId: string; +}; +/** + * Describes the message quixos.runtime.InvocationContext. + * Use `create(InvocationContextSchema)` to create a new message. + */ +export declare const InvocationContextSchema: GenMessage; +/** + * @generated from message quixos.runtime.InvocationControlRequest + */ +export type InvocationControlRequest = Message<"quixos.runtime.InvocationControlRequest"> & { + /** + * @generated from field: string invocation_id = 1; + */ + invocationId: string; +}; +/** + * Describes the message quixos.runtime.InvocationControlRequest. + * Use `create(InvocationControlRequestSchema)` to create a new message. + */ +export declare const InvocationControlRequestSchema: GenMessage; +/** + * @generated from message quixos.runtime.InvocationStatus + */ +export type InvocationStatus = Message<"quixos.runtime.InvocationStatus"> & { + /** + * @generated from field: string invocation_id = 1; + */ + invocationId: string; + /** + * unknown, running, cancellation-requested, completed, failed + * + * @generated from field: string state = 2; + */ + state: string; +}; +/** + * Describes the message quixos.runtime.InvocationStatus. + * Use `create(InvocationStatusSchema)` to create a new message. + */ +export declare const InvocationStatusSchema: GenMessage; /** * @generated from message quixos.runtime.InvokeRequest */ @@ -68,6 +154,10 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & { * @generated from field: repeated quixos.InjectedDependency dependencies = 5; */ dependencies: InjectedDependency[]; + /** + * @generated from field: quixos.runtime.InvocationContext context = 6; + */ + context?: InvocationContext | undefined; }; /** * Describes the message quixos.runtime.InvokeRequest. @@ -126,6 +216,10 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & { * @generated from field: repeated quixos.InjectedDependency dependencies = 5; */ dependencies: InjectedDependency[]; + /** + * @generated from field: quixos.runtime.InvocationContext context = 6; + */ + context?: InvocationContext | undefined; }; /** * Describes the message quixos.runtime.WatchRequest. @@ -216,5 +310,21 @@ export declare const PackageRuntime: GenService<{ input: typeof WatchRequestSchema; output: typeof WatchEventSchema; }; + /** + * @generated from rpc quixos.runtime.PackageRuntime.GetInvocationStatus + */ + getInvocationStatus: { + methodKind: "unary"; + input: typeof InvocationControlRequestSchema; + output: typeof InvocationStatusSchema; + }; + /** + * @generated from rpc quixos.runtime.PackageRuntime.CancelInvocation + */ + cancelInvocation: { + methodKind: "unary"; + input: typeof InvocationControlRequestSchema; + output: typeof InvocationStatusSchema; + }; }>; //# sourceMappingURL=runtime_pb.d.ts.map \ No newline at end of file diff --git a/dist/quixos/runtime_pb.d.ts.map b/dist/quixos/runtime_pb.d.ts.map index 4a0d418..f060c4b 100644 --- a/dist/quixos/runtime_pb.d.ts.map +++ b/dist/quixos/runtime_pb.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"runtime_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/runtime_pb.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"runtime_pb.d.ts","sourceRoot":"","sources":["../../src/quixos/runtime_pb.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/quixos/runtime_pb.js b/dist/quixos/runtime_pb.js index 698d8a6..7f257ea 100644 --- a/dist/quixos/runtime_pb.js +++ b/dist/quixos/runtime_pb.js @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/runtime.proto (package quixos.runtime, syntax proto3) /* eslint-disable */ import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2"; @@ -7,7 +7,7 @@ import { file_quixos_refs } from "./refs_pb.js"; /** * Describes the file quixos/runtime.proto. */ -export const file_quixos_runtime = /*@__PURE__*/ fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkiZgoRSGFuZHNoYWtlUmVzcG9uc2USGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgBIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAiABKAkSEgoKZXhwb3J0X2lkcxgDIAMoCSKLAgoNSW52b2tlUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI3CgVpbnB1dBgEIAMoCzIoLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASKDAQoOSW52b2tlUmVzcG9uc2USCgoCb2sYASABKAgSHQoGcmVzdWx0GAIgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAMgASgJEjcKDGRlcGVuZGVuY2llcxgEIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5IokCCgxXYXRjaFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNgoFaW5wdXQYBCADKAsyJy5xdWl4b3MucnVudGltZS5XYXRjaFJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDLwAQoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwAWIGcHJvdG8z", [file_camino_api, file_quixos_refs]); +export const file_quixos_runtime = /*@__PURE__*/ fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiQAoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkSDQoFbm9uY2UYAiABKAkirwEKEUhhbmRzaGFrZVJlc3BvbnNlEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAIgASgJEhIKCmV4cG9ydF9pZHMYAyADKAkSEwoLaW5zdGFuY2VfaWQYBCABKAkSHAoUYXV0aGVudGljYXRpb25fcHJvb2YYBSABKAkSFAoMY2FwYWJpbGl0aWVzGAYgAygJIpoBChFJbnZvY2F0aW9uQ29udGV4dBIXCg93b3Jrc3BhY2VfZXBvY2gYASABKAkSEwoLaW5zdGFuY2VfaWQYAiABKAkSFgoOYmluZGluZ19kaWdlc3QYAyABKAkSDQoFZ3JhbnQYBCABKAkSEgoKc2Vzc2lvbl9pZBgFIAEoCRIcChRvd25lcl9jb25mb3JtYW5jZV9pZBgGIAEoCSIxChhJbnZvY2F0aW9uQ29udHJvbFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCSI4ChBJbnZvY2F0aW9uU3RhdHVzEhUKDWludm9jYXRpb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkivwIKDUludm9rZVJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNwoFaW5wdXQYBCADKAsyKC5xdWl4b3MucnVudGltZS5JbnZva2VSZXF1ZXN0LklucHV0RW50cnkSMAoMZGVwZW5kZW5jaWVzGAUgAygLMhoucXVpeG9zLkluamVjdGVkRGVwZW5kZW5jeRIyCgdjb250ZXh0GAYgASgLMiEucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRleHQaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIoMBCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkSNwoMZGVwZW5kZW5jaWVzGAQgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kivQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kSMgoHY29udGV4dBgGIAEoCzIhLnF1aXhvcy5ydW50aW1lLkludm9jYXRpb25Db250ZXh0GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDKzAwoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwARJhChNHZXRJbnZvY2F0aW9uU3RhdHVzEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1cxJeChBDYW5jZWxJbnZvY2F0aW9uEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1c2IGcHJvdG8z", [file_camino_api, file_quixos_refs]); /** * Describes the message quixos.runtime.HandshakeRequest. * Use `create(HandshakeRequestSchema)` to create a new message. @@ -18,31 +18,46 @@ export const HandshakeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runt * Use `create(HandshakeResponseSchema)` to create a new message. */ export const HandshakeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 1); +/** + * Describes the message quixos.runtime.InvocationContext. + * Use `create(InvocationContextSchema)` to create a new message. + */ +export const InvocationContextSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 2); +/** + * Describes the message quixos.runtime.InvocationControlRequest. + * Use `create(InvocationControlRequestSchema)` to create a new message. + */ +export const InvocationControlRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 3); +/** + * Describes the message quixos.runtime.InvocationStatus. + * Use `create(InvocationStatusSchema)` to create a new message. + */ +export const InvocationStatusSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 4); /** * Describes the message quixos.runtime.InvokeRequest. * Use `create(InvokeRequestSchema)` to create a new message. */ -export const InvokeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 2); +export const InvokeRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 5); /** * Describes the message quixos.runtime.InvokeResponse. * Use `create(InvokeResponseSchema)` to create a new message. */ -export const InvokeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 3); +export const InvokeResponseSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 6); /** * Describes the message quixos.runtime.WatchRequest. * Use `create(WatchRequestSchema)` to create a new message. */ -export const WatchRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 4); +export const WatchRequestSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 7); /** * Describes the message quixos.runtime.DerivedDependency. * Use `create(DerivedDependencySchema)` to create a new message. */ -export const DerivedDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 5); +export const DerivedDependencySchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 8); /** * Describes the message quixos.runtime.WatchEvent. * Use `create(WatchEventSchema)` to create a new message. */ -export const WatchEventSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 6); +export const WatchEventSchema = /*@__PURE__*/ messageDesc(file_quixos_runtime, 9); /** * @generated from service quixos.runtime.PackageRuntime */ diff --git a/dist/references.d.ts b/dist/references.d.ts new file mode 100644 index 0000000..e3d6b0a --- /dev/null +++ b/dist/references.d.ts @@ -0,0 +1,14 @@ +declare const referenceBrand: unique symbol; +export interface QxObjectRef { + readonly [referenceBrand]: { + readonly [K in Identity]: true; + }; + equals(other: QxObjectRef): boolean; +} +export declare const isObjectReference: (value: unknown) => value is QxObjectRef; +/** Internal transport boundary; intentionally not exported from the SDK entry. */ +export declare const referenceFromWire: (id: string) => QxObjectRef; +export declare const referenceToWire: (value: unknown) => string; +export declare const assertReferenceFree: (value: unknown, seen?: Set) => void; +export {}; +//# sourceMappingURL=references.d.ts.map \ No newline at end of file diff --git a/dist/references.d.ts.map b/dist/references.d.ts.map new file mode 100644 index 0000000..9fa618a --- /dev/null +++ b/dist/references.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"references.d.ts","sourceRoot":"","sources":["../src/references.ts"],"names":[],"mappings":"AAGA,OAAO,CAAC,MAAM,cAAc,EAAE,OAAO,MAAM,CAAC;AAC5C,MAAM,WAAW,WAAW,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM;IAC3D,QAAQ,CAAC,CAAC,cAAc,CAAC,EAAE;QAAC,QAAQ,EAAE,CAAC,IAAI,QAAQ,GAAG,IAAI;KAAC,CAAC;IAC5D,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CAC7C;AAQD,eAAO,MAAM,iBAAiB,UAAW,OAAO,KAAG,KAAK,IAAI,WACU,CAAC;AAEvE,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,OAAQ,MAAM,KAAG,WAG9C,CAAC;AACF,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,MAGhD,CAAC;AACF,eAAO,MAAM,mBAAmB,UAAW,OAAO,yBAA6B,IAO9E,CAAC"} \ No newline at end of file diff --git a/dist/references.js b/dist/references.js new file mode 100644 index 0000000..74f234e --- /dev/null +++ b/dist/references.js @@ -0,0 +1,35 @@ +/** Opaque runtime identity. The wire codec, never ordinary package state, owns + * the raw ID. These handles do not themselves confer authority or a lease. */ +const identities = new WeakMap(); +class Reference { + constructor(id) { identities.set(this, id); Object.freeze(this); } + equals(other) { return isObjectReference(other) && identities.get(this) === identities.get(other); } + toJSON() { throw new Error("Object references cannot be serialized into ordinary data"); } + toString() { throw new Error("Object references cannot be coerced to strings"); } + [Symbol.toPrimitive]() { throw new Error("Object references cannot be coerced to scalar values"); } +} +export const isObjectReference = (value) => typeof value === "object" && value !== null && identities.has(value); +/** Internal transport boundary; intentionally not exported from the SDK entry. */ +export const referenceFromWire = (id) => { + if (typeof id !== "string" || !id) + throw new Error("Missing object reference identity"); + return new Reference(id); +}; +export const referenceToWire = (value) => { + if (!isObjectReference(value)) + throw new Error("Expected an opaque object reference, not a raw ID"); + return identities.get(value); +}; +export const assertReferenceFree = (value, seen = new Set()) => { + if (!value || typeof value !== "object") + return; + if (isObjectReference(value)) + throw new Error("Managed references belong in declared RPC references or graph relationships, not ordinary state/messages"); + if (seen.has(value)) + throw new Error("Cyclic ordinary data"); + seen.add(value); + if (!(value instanceof Uint8Array)) + for (const child of Object.values(value)) + assertReferenceFree(child, seen); + seen.delete(value); +}; diff --git a/dist/relationships.d.ts b/dist/relationships.d.ts new file mode 100644 index 0000000..1602517 --- /dev/null +++ b/dist/relationships.d.ts @@ -0,0 +1,30 @@ +import type { QxObjectRef } from "./references.js"; +import type { RelationshipCollection, RelationshipEntry } from "./index.js"; +type Key = string | boolean | bigint; +type Port = { + collection(): Promise>; + replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise>; +}; +/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */ +export declare const relationshipMap: (port: Port) => { + read: () => Promise>; + get(key: K): Promise<{ + revision: bigint; + value: T | undefined; + }>; + set(key: K, target: T, expectedRevision: bigint): Promise>; + delete(key: K, expectedRevision: bigint): Promise>; +}; +export declare const relationshipList: (port: Port) => { + read: () => Promise>; + insert(index: number, target: T, expectedRevision: bigint): Promise>; + move(edgeId: string, index: number, expectedRevision: bigint): Promise>; + delete(edgeId: string, expectedRevision: bigint): Promise>; +}; +export declare const relationshipSet: (port: Port) => { + read: () => Promise>; + add(target: T, expectedRevision: bigint): Promise>; + delete(target: T, expectedRevision: bigint): Promise>; +}; +export {}; +//# sourceMappingURL=relationships.d.ts.map \ No newline at end of file diff --git a/dist/relationships.d.ts.map b/dist/relationships.d.ts.map new file mode 100644 index 0000000..022dfdf --- /dev/null +++ b/dist/relationships.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"relationships.d.ts","sourceRoot":"","sources":["../src/relationships.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAC,sBAAsB,EAAE,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAC1E,KAAK,GAAG,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AACrC,KAAK,IAAI,CAAC,CAAC,SAAS,WAAW,IAAI;IAAC,UAAU,IAAI,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC;IAAC,OAAO,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAA;CAAC,CAAC;AAM9L,+EAA+E;AAC/E,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,GAAG,GAAG,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC;IACvF,IAAI;IACE,GAAG,MAAM,CAAC;;;;IACV,GAAG,MAAM,CAAC,UAAU,CAAC,oBAAoB,MAAM;IAO/C,MAAM,MAAM,CAAC,oBAAoB,MAAM;CAI7C,CAAC;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC;IACnE,IAAI;IACE,MAAM,QAAQ,MAAM,UAAU,CAAC,oBAAoB,MAAM;IAMzD,IAAI,SAAS,MAAM,SAAS,MAAM,oBAAoB,MAAM;IAQ5D,MAAM,SAAS,MAAM,oBAAoB,MAAM;CAKrD,CAAC;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,QAAQ,IAAI,CAAC,CAAC,CAAC;IAClE,IAAI;IACE,GAAG,SAAS,CAAC,oBAAoB,MAAM;IAKvC,MAAM,SAAS,CAAC,oBAAoB,MAAM;CAIhD,CAAC"} \ No newline at end of file diff --git a/dist/relationships.js b/dist/relationships.js new file mode 100644 index 0000000..9f1cb21 --- /dev/null +++ b/dist/relationships.js @@ -0,0 +1,60 @@ +const checked = async (port, revision) => { + const snapshot = await port.collection(); + if (snapshot.revision !== revision) + throw new Error("STALE_COLLECTION_REVISION"); + return snapshot; +}; +/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */ +export const relationshipMap = (port) => ({ + read: () => port.collection(), + async get(key) { const snapshot = await port.collection(); return { revision: snapshot.revision, value: snapshot.entries.find((entry) => entry.key === key)?.target }; }, + async set(key, target, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + const entries = snapshot.entries.filter((entry) => entry.key !== key); + const existing = snapshot.entries.find((entry) => entry.key === key && entry.target.equals(target)); + entries.push(existing ?? { key, target }); + return port.replace(entries, expectedRevision); + }, + async delete(key, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + return port.replace(snapshot.entries.filter((entry) => entry.key !== key), expectedRevision); + }, +}); +export const relationshipList = (port) => ({ + read: () => port.collection(), + async insert(index, target, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + if (!Number.isSafeInteger(index) || index < 0 || index > snapshot.entries.length) + throw new Error("List index out of bounds"); + snapshot.entries.splice(index, 0, { target }); + return port.replace(snapshot.entries, expectedRevision); + }, + async move(edgeId, index, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + const prior = snapshot.entries.findIndex((entry) => entry.edgeId === edgeId); + if (prior < 0 || !Number.isSafeInteger(index) || index < 0 || index >= snapshot.entries.length) + throw new Error("Unknown list entry or invalid index"); + const [entry] = snapshot.entries.splice(prior, 1); + snapshot.entries.splice(index, 0, entry); + return port.replace(snapshot.entries, expectedRevision); + }, + async delete(edgeId, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + if (!snapshot.entries.some((entry) => entry.edgeId === edgeId)) + throw new Error("Unknown list entry"); + return port.replace(snapshot.entries.filter((entry) => entry.edgeId !== edgeId), expectedRevision); + }, +}); +export const relationshipSet = (port) => ({ + read: () => port.collection(), + async add(target, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + if (snapshot.entries.some((entry) => entry.target.equals(target))) + return snapshot; + return port.replace([...snapshot.entries, { target }], expectedRevision); + }, + async delete(target, expectedRevision) { + const snapshot = await checked(port, expectedRevision); + return port.replace(snapshot.entries.filter((entry) => !entry.target.equals(target)), expectedRevision); + }, +}); diff --git a/src/bindings.ts b/src/bindings.ts index 8fa44e9..96a063f 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -3,14 +3,16 @@ import { ValueSchema, ObjectValueSchema, type Value } from "./camino/api_pb.js"; import { derived, jsToProtoValue, liveValue, protoValueToJs, type RuntimeContext, type RuntimeHandler, type DerivedHandler } from "./index.js"; -declare const referenceBrand: unique symbol; -export type QxObjectRef = string & { readonly [referenceBrand]: { readonly [K in Identity]: true } }; +export type { QxObjectRef } from "./references.js"; +import { assertReferenceFree, referenceToWire } from "./references.js"; declare const watchBrand: unique symbol; export type QxWatchHandle = string & { readonly [watchBrand]: true }; export type MessageBinding = { encode(value: T): Value; decode(value: Value): T }; export type BindingValue = B extends MessageBinding ? T : never; export type QxHandler = (context: C) => O | Promise; export type QxDerived = { kind: "derived"; get: QxHandler }; +export type QxSession = {id: string; run(work: (context: C) => Promise): Promise; close(): Promise}; +export type QxContextLifecycle = {signal?: AbortSignal; openSession?: () => Promise>}; export const qxDerived = (get: QxHandler): QxDerived => ({ kind: "derived", get }); /** Versioned binding ABI. This mirrors the language-neutral value IR. */ @@ -41,7 +43,17 @@ export const decodeQxValue = (type: QxValueType, value: Value | undefined, messa if (value.kind.case !== "listValue") throw new Error("Expected QX list"); return value.kind.value.values.map((entry) => decodeQxValue(type.value, entry, messages)); } - if (type.kind === "message") return requireMessage(messages, type.descriptorId).decode(value); + if (type.kind === "message") { + assertReferenceFree(protoValueToJs(value)); + const decoded = requireMessage(messages, type.descriptorId).decode(value); + assertReferenceFree(decoded); + return decoded; + } + if (type.kind === "object-ref") { + if (value.kind.case !== "refValue") throw new Error("Expected a declared RPC object reference"); + return protoValueToJs(value); + } + if (value.kind.case === "refValue") throw new Error("Reference supplied to a non-reference value"); if (type.kind === "scalar") { if (type.name === "int64" || type.name === "uint64") { if (value.kind.case !== "integerValue") throw new Error("Expected QX integer"); @@ -64,8 +76,13 @@ export const encodeQxValue = (type: QxValueType, value: any, messages: QxMessage if (type.kind === "builtin" && type.name === "unit") return jsToProtoValue(null); if (type.kind === "optional") return value === null ? jsToProtoValue(null) : encodeQxValue(type.value, value, messages); if (type.kind === "list") return jsToProtoValue(value.map((entry: unknown) => liveValue(encodeQxValue(type.value, entry, messages)))); - if (type.kind === "message") return requireMessage(messages, type.descriptorId).encode(value); - if (type.kind === "object-ref") return jsToProtoValue({ $quixosRef: value }); + if (type.kind === "object-ref") { referenceToWire(value); return jsToProtoValue(value); } + assertReferenceFree(value); + if (type.kind === "message") { + const encoded = requireMessage(messages, type.descriptorId).encode(value); + assertReferenceFree(protoValueToJs(encoded)); + return encoded; + } return jsToProtoValue(value); }; @@ -88,7 +105,7 @@ const inputFields = (type: QxValueType, value: unknown, messages: QxMessages): R export const bindQxHandler = ( spec: QxHandlerSpec, handler: QxHandler | QxDerived, messages: QxMessages, ): RuntimeHandler | DerivedHandler => { - const execute = async (raw: RuntimeContext) => { + const bindContext = (raw: RuntimeContext): C => { const ports = Object.fromEntries(Object.entries(spec.ports).map(([name, port]) => { switch (port.kind) { case "state": { @@ -100,7 +117,9 @@ export const bindQxHandler = ( } case "edge": { const edge = raw.edge(port.id); - return [name, Object.fromEntries(port.primitives.map((primitive) => [primitive, edge[primitive as "resolve" | "connect" | "disconnect"]]))]; + return [name, {...Object.fromEntries(port.primitives.map((primitive) => [primitive, edge[primitive as "resolve" | "connect" | "disconnect"]])), + ...(port.primitives.includes("resolve") ? {collection: edge.collection} : {}), + ...(port.primitives.includes("resolve") && port.primitives.includes("connect") && port.primitives.includes("disconnect") ? {replace: edge.replace} : {})}]; } case "interface": { const target = raw.interface(port.id); @@ -112,8 +131,16 @@ export const bindQxHandler = ( case "constructor": return [name, { construct: (input: unknown) => raw.constructor(port.id).construct(inputFields(port.inputType, input, messages)) }]; } })); - const context = { objectId: raw.objectId, + return { objectId: raw.objectId, signal: raw.signal, + ...(raw.openSession ? {openSession: async () => { + const session = await raw.openSession!(); + return {id: session.id, close: () => session.close(), + run: (work: (context: C) => Promise) => session.run((next) => work(bindContext(next)))}; + }} : {}), input: decodeQxValue(spec.inputType, inputValue(raw, spec.inputType), messages), ports } as C; + }; + const execute = async (raw: RuntimeContext) => { + const context = bindContext(raw); const value = await (typeof handler === "function" ? handler(context) : handler.get(context)); return liveValue(encodeQxValue(spec.eventType ?? spec.outputType, value, messages)); }; diff --git a/src/camino/api_pb.ts b/src/camino/api_pb.ts index f9ec35d..a8fe5e1 100644 --- a/src/camino/api_pb.ts +++ b/src/camino/api_pb.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file camino/api.proto (package camino, syntax proto3) /* eslint-disable */ @@ -12,7 +12,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file camino/api.proto. */ export const file_camino_api: GenFile = /*@__PURE__*/ - fileDesc("ChBjYW1pbm8vYXBpLnByb3RvEgZjYW1pbm8iCwoJTnVsbFZhbHVlInwKC09iamVjdFZhbHVlEi8KBmZpZWxkcxgBIAMoCzIfLmNhbWluby5PYmplY3RWYWx1ZS5GaWVsZHNFbnRyeRo8CgtGaWVsZHNFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIioKCUxpc3RWYWx1ZRIdCgZ2YWx1ZXMYASADKAsyDS5jYW1pbm8uVmFsdWUiHQoIUmVmVmFsdWUSEQoJb2JqZWN0X2lkGAEgASgJIjwKCUNyZHRWYWx1ZRIMCgR0eXBlGAEgASgJEhAKCGVuY29kaW5nGAIgASgJEg8KB3BheWxvYWQYAyABKAwiqAEKEFN0YXRlVmFsdWVTb3VyY2USEQoJb2JqZWN0X2lkGAEgASgJEg8KB3Nsb3RfaWQYAiABKAkSFwoPdmFsdWVfdHlwZV9qc29uGAMgASgJEhsKE3N0b3JhZ2VfcG9saWN5X2pzb24YBCABKAkSEAoIcmV2aXNpb24YBSABKAQSKAoNY3JkdF9zbmFwc2hvdBgGIAEoCzIRLmNhbWluby5DcmR0VmFsdWUiNgoLVmFsdWVTb3VyY2USJwoFc3RhdGUYASABKAsyGC5jYW1pbm8uU3RhdGVWYWx1ZVNvdXJjZSL5AgoFVmFsdWUSJwoKbnVsbF92YWx1ZRgBIAEoCzIRLmNhbWluby5OdWxsVmFsdWVIABIUCgpib29sX3ZhbHVlGAIgASgISAASFgoMbnVtYmVyX3ZhbHVlGAMgASgBSAASFgoMc3RyaW5nX3ZhbHVlGAQgASgJSAASFwoNaW50ZWdlcl92YWx1ZRgFIAEoCUgAEhUKC2J5dGVzX3ZhbHVlGAYgASgMSAASKwoMb2JqZWN0X3ZhbHVlGAcgASgLMhMuY2FtaW5vLk9iamVjdFZhbHVlSAASJwoKbGlzdF92YWx1ZRgIIAEoCzIRLmNhbWluby5MaXN0VmFsdWVIABIlCglyZWZfdmFsdWUYCSABKAsyEC5jYW1pbm8uUmVmVmFsdWVIABInCgpjcmR0X3ZhbHVlGAogASgLMhEuY2FtaW5vLkNyZHRWYWx1ZUgAEiMKBnNvdXJjZRgLIAEoCzITLmNhbWluby5WYWx1ZVNvdXJjZUIGCgRraW5kIkYKHUluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0EiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIkcKHkluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXNwb25zZRIlCgRwbGFuGAEgASgLMhcuY2FtaW5vLlBlcnNpc3RlbmNlUGxhbiIbChlHZXRQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0IkMKGkdldFBlcnNpc3RlbmNlUGxhblJlc3BvbnNlEiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIrABChNDcmVhdGVPYmplY3RSZXF1ZXN0Eg8KB2F0b21faWQYASABKAkSRAoNaW5pdGlhbF9zdGF0ZRgCIAMoCzItLmNhbWluby5DcmVhdGVPYmplY3RSZXF1ZXN0LkluaXRpYWxTdGF0ZUVudHJ5GkIKEUluaXRpYWxTdGF0ZUVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPAoUQ3JlYXRlT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCIlChBHZXRPYmplY3RSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCSI5ChFHZXRPYmplY3RSZXNwb25zZRIkCgZvYmplY3QYASABKAsyFC5jYW1pbm8uQ2FtaW5vT2JqZWN0IiUKEkxpc3RPYmplY3RzUmVxdWVzdBIPCgdhdG9tX2lkGAEgASgJIjwKE0xpc3RPYmplY3RzUmVzcG9uc2USJQoHb2JqZWN0cxgBIAMoCzIULmNhbWluby5DYW1pbm9PYmplY3QiNgoQUmVhZFN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCSIxChFSZWFkU3RhdGVSZXNwb25zZRIcCgV2YWx1ZRgBIAEoCzINLmNhbWluby5WYWx1ZSJxChFXcml0ZVN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCRIcCgV2YWx1ZRgDIAEoCzINLmNhbWluby5WYWx1ZRIaChJjbGllbnRfbXV0YXRpb25faWQYBCABKAkiWAoSV3JpdGVTdGF0ZVJlc3BvbnNlEhwKBXZhbHVlGAEgASgLMg0uY2FtaW5vLlZhbHVlEiQKBm9iamVjdBgCIAEoCzIULmNhbWluby5DYW1pbm9PYmplY3QiwAEKEkNvbm5lY3RFZGdlUmVxdWVzdBIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCRIRCglvYmplY3RfaWQYAyABKAkSGAoQdGFyZ2V0X29iamVjdF9pZBgEIAEoCRIUCgdvcmRpbmFsGAUgASgFSACIAQESGwoOdGFyZ2V0X29yZGluYWwYBiABKAVIAYgBAUIKCghfb3JkaW5hbEIRCg9fdGFyZ2V0X29yZGluYWwiNwoTQ29ubmVjdEVkZ2VSZXNwb25zZRIgCgRlZGdlGAEgASgLMhIuY2FtaW5vLkNhbWlub0VkZ2UiVAoSUmVzb2x2ZUVkZ2VSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCRIUCgxlZGdlX3R5cGVfaWQYAiABKAkSFQoNcHJvamVjdGlvbl9pZBgDIAEoCSI4ChNSZXNvbHZlRWRnZVJlc3BvbnNlEiEKBWVkZ2VzGAEgAygLMhIuY2FtaW5vLkNhbWlub0VkZ2UiKAoVRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Eg8KB2VkZ2VfaWQYASABKAkiKQoWRGlzY29ubmVjdEVkZ2VSZXNwb25zZRIPCgdlZGdlX2lkGAEgASgJIiMKDkxpc3RPcHNSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCSIwCg9MaXN0T3BzUmVzcG9uc2USHQoDb3BzGAEgAygLMhAuY2FtaW5vLkNhbWlub09wIlYKEldhdGNoT2JqZWN0UmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSEwoLYWZ0ZXJfb3BfaWQYAiABKAkSGAoQaW5jbHVkZV9zbmFwc2hvdBgDIAEoCCJrChBXYXRjaE9iamVjdEV2ZW50EhEKCW9iamVjdF9pZBgBIAEoCRImCghzbmFwc2hvdBgCIAEoCzIULmNhbWluby5DYW1pbm9PYmplY3QSHAoCb3AYAyABKAsyEC5jYW1pbm8uQ2FtaW5vT3Ai2QIKDENhbWlub09iamVjdBIKCgJpZBgBIAEoCRIPCgdhdG9tX2lkGAIgASgJEh0KFXdvcmtzcGFjZV9yZXZpc2lvbl9pZBgDIAEoCRISCgpjcmVhdGVkX2F0GAQgASgJEhIKCnVwZGF0ZWRfYXQYBSABKAkSLgoFc3RhdGUYBiADKAsyHy5jYW1pbm8uQ2FtaW5vT2JqZWN0LlN0YXRlRW50cnkSQQoPc3RhdGVfcmV2aXNpb25zGAcgAygLMiguY2FtaW5vLkNhbWlub09iamVjdC5TdGF0ZVJldmlzaW9uc0VudHJ5GjsKClN0YXRlRW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ARo1ChNTdGF0ZVJldmlzaW9uc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBDoCOAEijgIKCkNhbWlub0VkZ2USCgoCaWQYASABKAkSFAoMZWRnZV90eXBlX2lkGAIgASgJEhcKD2ZpcnN0X29iamVjdF9pZBgDIAEoCRIYChBzZWNvbmRfb2JqZWN0X2lkGAQgASgJEhsKE2ZpcnN0X3Byb2plY3Rpb25faWQYBSABKAkSHAoUc2Vjb25kX3Byb2plY3Rpb25faWQYBiABKAkSGgoNZmlyc3Rfb3JkaW5hbBgHIAEoBUgAiAEBEhsKDnNlY29uZF9vcmRpbmFsGAggASgFSAGIAQESEgoKY3JlYXRlZF9hdBgJIAEoCUIQCg5fZmlyc3Rfb3JkaW5hbEIRCg9fc2Vjb25kX29yZGluYWwimQEKCENhbWlub09wEgoKAmlkGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIPCgdvcF9raW5kGAMgASgJEh4KB3BheWxvYWQYBCABKAsyDS5jYW1pbm8uVmFsdWUSDQoFYWN0b3IYBSABKAkSEgoKY3JlYXRlZF9hdBgGIAEoCRIaChJjbGllbnRfbXV0YXRpb25faWQYByABKAkylQcKDUNhbWlub1NlcnZpY2USZwoWSW5zdGFsbFBlcnNpc3RlbmNlUGxhbhIlLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVxdWVzdBomLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USWwoSR2V0UGVyc2lzdGVuY2VQbGFuEiEuY2FtaW5vLkdldFBlcnNpc3RlbmNlUGxhblJlcXVlc3QaIi5jYW1pbm8uR2V0UGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USSQoMQ3JlYXRlT2JqZWN0EhsuY2FtaW5vLkNyZWF0ZU9iamVjdFJlcXVlc3QaHC5jYW1pbm8uQ3JlYXRlT2JqZWN0UmVzcG9uc2USQAoJR2V0T2JqZWN0EhguY2FtaW5vLkdldE9iamVjdFJlcXVlc3QaGS5jYW1pbm8uR2V0T2JqZWN0UmVzcG9uc2USRgoLTGlzdE9iamVjdHMSGi5jYW1pbm8uTGlzdE9iamVjdHNSZXF1ZXN0GhsuY2FtaW5vLkxpc3RPYmplY3RzUmVzcG9uc2USQAoJUmVhZFN0YXRlEhguY2FtaW5vLlJlYWRTdGF0ZVJlcXVlc3QaGS5jYW1pbm8uUmVhZFN0YXRlUmVzcG9uc2USQwoKV3JpdGVTdGF0ZRIZLmNhbWluby5Xcml0ZVN0YXRlUmVxdWVzdBoaLmNhbWluby5Xcml0ZVN0YXRlUmVzcG9uc2USRgoLQ29ubmVjdEVkZ2USGi5jYW1pbm8uQ29ubmVjdEVkZ2VSZXF1ZXN0GhsuY2FtaW5vLkNvbm5lY3RFZGdlUmVzcG9uc2USRgoLUmVzb2x2ZUVkZ2USGi5jYW1pbm8uUmVzb2x2ZUVkZ2VSZXF1ZXN0GhsuY2FtaW5vLlJlc29sdmVFZGdlUmVzcG9uc2USTwoORGlzY29ubmVjdEVkZ2USHS5jYW1pbm8uRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Gh4uY2FtaW5vLkRpc2Nvbm5lY3RFZGdlUmVzcG9uc2USOgoHTGlzdE9wcxIWLmNhbWluby5MaXN0T3BzUmVxdWVzdBoXLmNhbWluby5MaXN0T3BzUmVzcG9uc2USRQoLV2F0Y2hPYmplY3QSGi5jYW1pbm8uV2F0Y2hPYmplY3RSZXF1ZXN0GhguY2FtaW5vLldhdGNoT2JqZWN0RXZlbnQwAWIGcHJvdG8z", [file_camino_schema]); + fileDesc("ChBjYW1pbm8vYXBpLnByb3RvEgZjYW1pbm8iCwoJTnVsbFZhbHVlInwKC09iamVjdFZhbHVlEi8KBmZpZWxkcxgBIAMoCzIfLmNhbWluby5PYmplY3RWYWx1ZS5GaWVsZHNFbnRyeRo8CgtGaWVsZHNFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIioKCUxpc3RWYWx1ZRIdCgZ2YWx1ZXMYASADKAsyDS5jYW1pbm8uVmFsdWUiHQoIUmVmVmFsdWUSEQoJb2JqZWN0X2lkGAEgASgJIjwKCUNyZHRWYWx1ZRIMCgR0eXBlGAEgASgJEhAKCGVuY29kaW5nGAIgASgJEg8KB3BheWxvYWQYAyABKAwiqAEKEFN0YXRlVmFsdWVTb3VyY2USEQoJb2JqZWN0X2lkGAEgASgJEg8KB3Nsb3RfaWQYAiABKAkSFwoPdmFsdWVfdHlwZV9qc29uGAMgASgJEhsKE3N0b3JhZ2VfcG9saWN5X2pzb24YBCABKAkSEAoIcmV2aXNpb24YBSABKAQSKAoNY3JkdF9zbmFwc2hvdBgGIAEoCzIRLmNhbWluby5DcmR0VmFsdWUiNgoLVmFsdWVTb3VyY2USJwoFc3RhdGUYASABKAsyGC5jYW1pbm8uU3RhdGVWYWx1ZVNvdXJjZSL5AgoFVmFsdWUSJwoKbnVsbF92YWx1ZRgBIAEoCzIRLmNhbWluby5OdWxsVmFsdWVIABIUCgpib29sX3ZhbHVlGAIgASgISAASFgoMbnVtYmVyX3ZhbHVlGAMgASgBSAASFgoMc3RyaW5nX3ZhbHVlGAQgASgJSAASFwoNaW50ZWdlcl92YWx1ZRgFIAEoCUgAEhUKC2J5dGVzX3ZhbHVlGAYgASgMSAASKwoMb2JqZWN0X3ZhbHVlGAcgASgLMhMuY2FtaW5vLk9iamVjdFZhbHVlSAASJwoKbGlzdF92YWx1ZRgIIAEoCzIRLmNhbWluby5MaXN0VmFsdWVIABIlCglyZWZfdmFsdWUYCSABKAsyEC5jYW1pbm8uUmVmVmFsdWVIABInCgpjcmR0X3ZhbHVlGAogASgLMhEuY2FtaW5vLkNyZHRWYWx1ZUgAEiMKBnNvdXJjZRgLIAEoCzITLmNhbWluby5WYWx1ZVNvdXJjZUIGCgRraW5kIkYKHUluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0EiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIkcKHkluc3RhbGxQZXJzaXN0ZW5jZVBsYW5SZXNwb25zZRIlCgRwbGFuGAEgASgLMhcuY2FtaW5vLlBlcnNpc3RlbmNlUGxhbiIbChlHZXRQZXJzaXN0ZW5jZVBsYW5SZXF1ZXN0IkMKGkdldFBlcnNpc3RlbmNlUGxhblJlc3BvbnNlEiUKBHBsYW4YASABKAsyFy5jYW1pbm8uUGVyc2lzdGVuY2VQbGFuIrABChNDcmVhdGVPYmplY3RSZXF1ZXN0Eg8KB2F0b21faWQYASABKAkSRAoNaW5pdGlhbF9zdGF0ZRgCIAMoCzItLmNhbWluby5DcmVhdGVPYmplY3RSZXF1ZXN0LkluaXRpYWxTdGF0ZUVudHJ5GkIKEUluaXRpYWxTdGF0ZUVudHJ5EgsKA2tleRgBIAEoCRIcCgV2YWx1ZRgCIAEoCzINLmNhbWluby5WYWx1ZToCOAEiPAoUQ3JlYXRlT2JqZWN0UmVzcG9uc2USJAoGb2JqZWN0GAEgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdCIlChBHZXRPYmplY3RSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCSI5ChFHZXRPYmplY3RSZXNwb25zZRIkCgZvYmplY3QYASABKAsyFC5jYW1pbm8uQ2FtaW5vT2JqZWN0IiUKEkxpc3RPYmplY3RzUmVxdWVzdBIPCgdhdG9tX2lkGAEgASgJIjwKE0xpc3RPYmplY3RzUmVzcG9uc2USJQoHb2JqZWN0cxgBIAMoCzIULmNhbWluby5DYW1pbm9PYmplY3QiNgoQUmVhZFN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCSIxChFSZWFkU3RhdGVSZXNwb25zZRIcCgV2YWx1ZRgBIAEoCzINLmNhbWluby5WYWx1ZSJxChFXcml0ZVN0YXRlUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSDwoHc2xvdF9pZBgCIAEoCRIcCgV2YWx1ZRgDIAEoCzINLmNhbWluby5WYWx1ZRIaChJjbGllbnRfbXV0YXRpb25faWQYBCABKAkiWAoSV3JpdGVTdGF0ZVJlc3BvbnNlEhwKBXZhbHVlGAEgASgLMg0uY2FtaW5vLlZhbHVlEiQKBm9iamVjdBgCIAEoCzIULmNhbWluby5DYW1pbm9PYmplY3QiwAEKEkNvbm5lY3RFZGdlUmVxdWVzdBIUCgxlZGdlX3R5cGVfaWQYASABKAkSFQoNcHJvamVjdGlvbl9pZBgCIAEoCRIRCglvYmplY3RfaWQYAyABKAkSGAoQdGFyZ2V0X29iamVjdF9pZBgEIAEoCRIUCgdvcmRpbmFsGAUgASgFSACIAQESGwoOdGFyZ2V0X29yZGluYWwYBiABKAVIAYgBAUIKCghfb3JkaW5hbEIRCg9fdGFyZ2V0X29yZGluYWwiNwoTQ29ubmVjdEVkZ2VSZXNwb25zZRIgCgRlZGdlGAEgASgLMhIuY2FtaW5vLkNhbWlub0VkZ2UiVAoSUmVzb2x2ZUVkZ2VSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCRIUCgxlZGdlX3R5cGVfaWQYAiABKAkSFQoNcHJvamVjdGlvbl9pZBgDIAEoCSI4ChNSZXNvbHZlRWRnZVJlc3BvbnNlEiEKBWVkZ2VzGAEgAygLMhIuY2FtaW5vLkNhbWlub0VkZ2UiKAoVRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Eg8KB2VkZ2VfaWQYASABKAkiKQoWRGlzY29ubmVjdEVkZ2VSZXNwb25zZRIPCgdlZGdlX2lkGAEgASgJIlgKD0NvbGxlY3Rpb25FbnRyeRIPCgdlZGdlX2lkGAEgASgJEhgKEHRhcmdldF9vYmplY3RfaWQYAiABKAkSGgoDa2V5GAMgASgLMg0uY2FtaW5vLlZhbHVlIlQKFlJlYWRDb2xsZWN0aW9uUmVzcG9uc2USEAoIcmV2aXNpb24YASABKAQSKAoHZW50cmllcxgCIAMoCzIXLmNhbWluby5Db2xsZWN0aW9uRW50cnkinwEKGFJlcGxhY2VDb2xsZWN0aW9uUmVxdWVzdBIRCglvYmplY3RfaWQYASABKAkSFAoMZWRnZV90eXBlX2lkGAIgASgJEhUKDXByb2plY3Rpb25faWQYAyABKAkSGQoRZXhwZWN0ZWRfcmV2aXNpb24YBCABKAQSKAoHZW50cmllcxgFIAMoCzIXLmNhbWluby5Db2xsZWN0aW9uRW50cnkiIwoOTGlzdE9wc1JlcXVlc3QSEQoJb2JqZWN0X2lkGAEgASgJIjAKD0xpc3RPcHNSZXNwb25zZRIdCgNvcHMYASADKAsyEC5jYW1pbm8uQ2FtaW5vT3AibgoSV2F0Y2hPYmplY3RSZXF1ZXN0EhEKCW9iamVjdF9pZBgBIAEoCRITCgthZnRlcl9vcF9pZBgCIAEoCRIYChBpbmNsdWRlX3NuYXBzaG90GAMgASgIEhYKDmF0dGFjaG1lbnRfaWRzGAQgAygJImsKEFdhdGNoT2JqZWN0RXZlbnQSEQoJb2JqZWN0X2lkGAEgASgJEiYKCHNuYXBzaG90GAIgASgLMhQuY2FtaW5vLkNhbWlub09iamVjdBIcCgJvcBgDIAEoCzIQLmNhbWluby5DYW1pbm9PcCLZAgoMQ2FtaW5vT2JqZWN0EgoKAmlkGAEgASgJEg8KB2F0b21faWQYAiABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAMgASgJEhIKCmNyZWF0ZWRfYXQYBCABKAkSEgoKdXBkYXRlZF9hdBgFIAEoCRIuCgVzdGF0ZRgGIAMoCzIfLmNhbWluby5DYW1pbm9PYmplY3QuU3RhdGVFbnRyeRJBCg9zdGF0ZV9yZXZpc2lvbnMYByADKAsyKC5jYW1pbm8uQ2FtaW5vT2JqZWN0LlN0YXRlUmV2aXNpb25zRW50cnkaOwoKU3RhdGVFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBGjUKE1N0YXRlUmV2aXNpb25zRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgEOgI4ASK/AgoKQ2FtaW5vRWRnZRIKCgJpZBgBIAEoCRIUCgxlZGdlX3R5cGVfaWQYAiABKAkSFwoPZmlyc3Rfb2JqZWN0X2lkGAMgASgJEhgKEHNlY29uZF9vYmplY3RfaWQYBCABKAkSGwoTZmlyc3RfcHJvamVjdGlvbl9pZBgFIAEoCRIcChRzZWNvbmRfcHJvamVjdGlvbl9pZBgGIAEoCRIaCg1maXJzdF9vcmRpbmFsGAcgASgFSACIAQESGwoOc2Vjb25kX29yZGluYWwYCCABKAVIAYgBARISCgpjcmVhdGVkX2F0GAkgASgJEhYKDmZpcnN0X2tleV9qc29uGAogASgJEhcKD3NlY29uZF9rZXlfanNvbhgLIAEoCUIQCg5fZmlyc3Rfb3JkaW5hbEIRCg9fc2Vjb25kX29yZGluYWwimQEKCENhbWlub09wEgoKAmlkGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIPCgdvcF9raW5kGAMgASgJEh4KB3BheWxvYWQYBCABKAsyDS5jYW1pbm8uVmFsdWUSDQoFYWN0b3IYBSABKAkSEgoKY3JlYXRlZF9hdBgGIAEoCRIaChJjbGllbnRfbXV0YXRpb25faWQYByABKAkyuggKDUNhbWlub1NlcnZpY2USZwoWSW5zdGFsbFBlcnNpc3RlbmNlUGxhbhIlLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVxdWVzdBomLmNhbWluby5JbnN0YWxsUGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USWwoSR2V0UGVyc2lzdGVuY2VQbGFuEiEuY2FtaW5vLkdldFBlcnNpc3RlbmNlUGxhblJlcXVlc3QaIi5jYW1pbm8uR2V0UGVyc2lzdGVuY2VQbGFuUmVzcG9uc2USSQoMQ3JlYXRlT2JqZWN0EhsuY2FtaW5vLkNyZWF0ZU9iamVjdFJlcXVlc3QaHC5jYW1pbm8uQ3JlYXRlT2JqZWN0UmVzcG9uc2USQAoJR2V0T2JqZWN0EhguY2FtaW5vLkdldE9iamVjdFJlcXVlc3QaGS5jYW1pbm8uR2V0T2JqZWN0UmVzcG9uc2USRgoLTGlzdE9iamVjdHMSGi5jYW1pbm8uTGlzdE9iamVjdHNSZXF1ZXN0GhsuY2FtaW5vLkxpc3RPYmplY3RzUmVzcG9uc2USQAoJUmVhZFN0YXRlEhguY2FtaW5vLlJlYWRTdGF0ZVJlcXVlc3QaGS5jYW1pbm8uUmVhZFN0YXRlUmVzcG9uc2USQwoKV3JpdGVTdGF0ZRIZLmNhbWluby5Xcml0ZVN0YXRlUmVxdWVzdBoaLmNhbWluby5Xcml0ZVN0YXRlUmVzcG9uc2USRgoLQ29ubmVjdEVkZ2USGi5jYW1pbm8uQ29ubmVjdEVkZ2VSZXF1ZXN0GhsuY2FtaW5vLkNvbm5lY3RFZGdlUmVzcG9uc2USRgoLUmVzb2x2ZUVkZ2USGi5jYW1pbm8uUmVzb2x2ZUVkZ2VSZXF1ZXN0GhsuY2FtaW5vLlJlc29sdmVFZGdlUmVzcG9uc2USTwoORGlzY29ubmVjdEVkZ2USHS5jYW1pbm8uRGlzY29ubmVjdEVkZ2VSZXF1ZXN0Gh4uY2FtaW5vLkRpc2Nvbm5lY3RFZGdlUmVzcG9uc2USTAoOUmVhZENvbGxlY3Rpb24SGi5jYW1pbm8uUmVzb2x2ZUVkZ2VSZXF1ZXN0Gh4uY2FtaW5vLlJlYWRDb2xsZWN0aW9uUmVzcG9uc2USVQoRUmVwbGFjZUNvbGxlY3Rpb24SIC5jYW1pbm8uUmVwbGFjZUNvbGxlY3Rpb25SZXF1ZXN0Gh4uY2FtaW5vLlJlYWRDb2xsZWN0aW9uUmVzcG9uc2USOgoHTGlzdE9wcxIWLmNhbWluby5MaXN0T3BzUmVxdWVzdBoXLmNhbWluby5MaXN0T3BzUmVzcG9uc2USRQoLV2F0Y2hPYmplY3QSGi5jYW1pbm8uV2F0Y2hPYmplY3RSZXF1ZXN0GhguY2FtaW5vLldhdGNoT2JqZWN0RXZlbnQwAWIGcHJvdG8z", [file_camino_schema]); /** * @generated from message camino.NullValue @@ -651,6 +651,94 @@ export type DisconnectEdgeResponse = Message<"camino.DisconnectEdgeResponse"> & export const DisconnectEdgeResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_camino_api, 27); +/** + * @generated from message camino.CollectionEntry + */ +export type CollectionEntry = Message<"camino.CollectionEntry"> & { + /** + * Existing entry identity to preserve; empty allocates a new canonical edge. + * + * @generated from field: string edge_id = 1; + */ + edgeId: string; + + /** + * @generated from field: string target_object_id = 2; + */ + targetObjectId: string; + + /** + * @generated from field: camino.Value key = 3; + */ + key?: Value | undefined; +}; + +/** + * Describes the message camino.CollectionEntry. + * Use `create(CollectionEntrySchema)` to create a new message. + */ +export const CollectionEntrySchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_api, 28); + +/** + * @generated from message camino.ReadCollectionResponse + */ +export type ReadCollectionResponse = Message<"camino.ReadCollectionResponse"> & { + /** + * @generated from field: uint64 revision = 1; + */ + revision: bigint; + + /** + * @generated from field: repeated camino.CollectionEntry entries = 2; + */ + entries: CollectionEntry[]; +}; + +/** + * Describes the message camino.ReadCollectionResponse. + * Use `create(ReadCollectionResponseSchema)` to create a new message. + */ +export const ReadCollectionResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_api, 29); + +/** + * @generated from message camino.ReplaceCollectionRequest + */ +export type ReplaceCollectionRequest = Message<"camino.ReplaceCollectionRequest"> & { + /** + * @generated from field: string object_id = 1; + */ + objectId: string; + + /** + * @generated from field: string edge_type_id = 2; + */ + edgeTypeId: string; + + /** + * @generated from field: string projection_id = 3; + */ + projectionId: string; + + /** + * @generated from field: uint64 expected_revision = 4; + */ + expectedRevision: bigint; + + /** + * @generated from field: repeated camino.CollectionEntry entries = 5; + */ + entries: CollectionEntry[]; +}; + +/** + * Describes the message camino.ReplaceCollectionRequest. + * Use `create(ReplaceCollectionRequestSchema)` to create a new message. + */ +export const ReplaceCollectionRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_camino_api, 30); + /** * @generated from message camino.ListOpsRequest */ @@ -666,7 +754,7 @@ export type ListOpsRequest = Message<"camino.ListOpsRequest"> & { * Use `create(ListOpsRequestSchema)` to create a new message. */ export const ListOpsRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 28); + messageDesc(file_camino_api, 31); /** * @generated from message camino.ListOpsResponse @@ -683,7 +771,7 @@ export type ListOpsResponse = Message<"camino.ListOpsResponse"> & { * Use `create(ListOpsResponseSchema)` to create a new message. */ export const ListOpsResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 29); + messageDesc(file_camino_api, 32); /** * @generated from message camino.WatchObjectRequest @@ -703,6 +791,13 @@ export type WatchObjectRequest = Message<"camino.WatchObjectRequest"> & { * @generated from field: bool include_snapshot = 3; */ includeSnapshot: boolean; + + /** + * Managed runtimes must watch only their injected attachments. + * + * @generated from field: repeated string attachment_ids = 4; + */ + attachmentIds: string[]; }; /** @@ -710,7 +805,7 @@ export type WatchObjectRequest = Message<"camino.WatchObjectRequest"> & { * Use `create(WatchObjectRequestSchema)` to create a new message. */ export const WatchObjectRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 30); + messageDesc(file_camino_api, 33); /** * @generated from message camino.WatchObjectEvent @@ -737,7 +832,7 @@ export type WatchObjectEvent = Message<"camino.WatchObjectEvent"> & { * Use `create(WatchObjectEventSchema)` to create a new message. */ export const WatchObjectEventSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 31); + messageDesc(file_camino_api, 34); /** * @generated from message camino.CaminoObject @@ -784,7 +879,7 @@ export type CaminoObject = Message<"camino.CaminoObject"> & { * Use `create(CaminoObjectSchema)` to create a new message. */ export const CaminoObjectSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 32); + messageDesc(file_camino_api, 35); /** * @generated from message camino.CaminoEdge @@ -834,6 +929,16 @@ export type CaminoEdge = Message<"camino.CaminoEdge"> & { * @generated from field: string created_at = 9; */ createdAt: string; + + /** + * @generated from field: string first_key_json = 10; + */ + firstKeyJson: string; + + /** + * @generated from field: string second_key_json = 11; + */ + secondKeyJson: string; }; /** @@ -841,7 +946,7 @@ export type CaminoEdge = Message<"camino.CaminoEdge"> & { * Use `create(CaminoEdgeSchema)` to create a new message. */ export const CaminoEdgeSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 33); + messageDesc(file_camino_api, 36); /** * @generated from message camino.CaminoOp @@ -888,7 +993,7 @@ export type CaminoOp = Message<"camino.CaminoOp"> & { * Use `create(CaminoOpSchema)` to create a new message. */ export const CaminoOpSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_camino_api, 34); + messageDesc(file_camino_api, 37); /** * @generated from service camino.CaminoService @@ -974,6 +1079,22 @@ export const CaminoService: GenService<{ input: typeof DisconnectEdgeRequestSchema; output: typeof DisconnectEdgeResponseSchema; }, + /** + * @generated from rpc camino.CaminoService.ReadCollection + */ + readCollection: { + methodKind: "unary"; + input: typeof ResolveEdgeRequestSchema; + output: typeof ReadCollectionResponseSchema; + }, + /** + * @generated from rpc camino.CaminoService.ReplaceCollection + */ + replaceCollection: { + methodKind: "unary"; + input: typeof ReplaceCollectionRequestSchema; + output: typeof ReadCollectionResponseSchema; + }, /** * @generated from rpc camino.CaminoService.ListOps */ diff --git a/src/camino/schema_pb.ts b/src/camino/schema_pb.ts index d783f7b..3cbbaef 100644 --- a/src/camino/schema_pb.ts +++ b/src/camino/schema_pb.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file camino/schema.proto (package camino, syntax proto3) /* eslint-disable */ @@ -10,7 +10,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file camino/schema.proto. */ export const file_camino_schema: GenFile = /*@__PURE__*/ - fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiQQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJIqQBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIqYBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCCKHAQoORWRnZUF0dGFjaG1lbnQSFAoMZWRnZV90eXBlX2lkGAEgASgJEhQKDGRpc3BsYXlfbmFtZRgCIAEoCRIjCgVmaXJzdBgDIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSJAoGc2Vjb25kGAQgASgLMhQuY2FtaW5vLkVkZ2VFbmRwb2ludCLsAQoPUGVyc2lzdGVuY2VQbGFuEhQKDHdvcmtzcGFjZV9pZBgBIAEoCRIdChV3b3Jrc3BhY2VfcmV2aXNpb25faWQYAiABKAkSJQoFYXRvbXMYAyADKAsyFi5jYW1pbm8uQXRvbURlZmluaXRpb24SLQoMY29uZm9ybWFuY2VzGAQgAygLMhcuY2FtaW5vLkF0b21Db25mb3JtYW5jZRInCgZzdGF0ZXMYBSADKAsyFy5jYW1pbm8uU3RhdGVBdHRhY2htZW50EiUKBWVkZ2VzGAYgAygLMhYuY2FtaW5vLkVkZ2VBdHRhY2htZW50KmgKC0NhcmRpbmFsaXR5EhsKF0NBUkRJTkFMSVRZX1VOU1BFQ0lGSUVEEAASEAoMT1BUSU9OQUxfT05FEAESDwoLRVhBQ1RMWV9PTkUQAhIICgRNQU5ZEAMSDwoLTUFOWV9VTklRVUUQBGIGcHJvdG8z"); + fileDesc("ChNjYW1pbm8vc2NoZW1hLnByb3RvEgZjYW1pbm8iNwoOQXRvbURlZmluaXRpb24SDwoHYXRvbV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkiWQoPQXRvbUNvbmZvcm1hbmNlEg8KB2F0b21faWQYASABKAkSHQoVaW50ZXJmYWNlX3JldmlzaW9uX2lkGAIgASgJEhYKDmNvbmZvcm1hbmNlX2lkGAMgASgJIsIBCg9TdGF0ZUF0dGFjaG1lbnQSDwoHc2xvdF9pZBgBIAEoCRIYChBhdHRhY2hlZF9hdG9tX2lkGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRIXCg92YWx1ZV90eXBlX2pzb24YBCABKAkSGwoTc3RvcmFnZV9wb2xpY3lfanNvbhgFIAEoCRIaChJkZWZhdWx0X3ZhbHVlX2pzb24YBiABKAkSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYByABKAkiUAoSRW5kcG9pbnRDb25zdHJhaW50EhEKB2F0b21faWQYASABKAlIABIfChVpbnRlcmZhY2VfcmV2aXNpb25faWQYAiABKAlIAEIGCgRraW5kIvsBCgxFZGdlRW5kcG9pbnQSFQoNcHJvamVjdGlvbl9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSLgoKY29uc3RyYWludBgDIAEoCzIaLmNhbWluby5FbmRwb2ludENvbnN0cmFpbnQSKAoLY2FyZGluYWxpdHkYBCABKA4yEy5jYW1pbm8uQ2FyZGluYWxpdHkSDwoHb3JkZXJlZBgFIAEoCBIRCglvbl9kZWxldGUYBiABKAkSFAoMcmV0YWluX290aGVyGAcgASgIEhAKCGtleV90eXBlGAggASgJEhgKEHB1YmxpY190cmF2ZXJzYWwYCSABKAgipQEKDkVkZ2VBdHRhY2htZW50EhQKDGVkZ2VfdHlwZV9pZBgBIAEoCRIUCgxkaXNwbGF5X25hbWUYAiABKAkSIwoFZmlyc3QYAyABKAsyFC5jYW1pbm8uRWRnZUVuZHBvaW50EiQKBnNlY29uZBgEIAEoCzIULmNhbWluby5FZGdlRW5kcG9pbnQSHAoUb3duZXJfY29uZm9ybWFuY2VfaWQYBSABKAki7AEKD1BlcnNpc3RlbmNlUGxhbhIUCgx3b3Jrc3BhY2VfaWQYASABKAkSHQoVd29ya3NwYWNlX3JldmlzaW9uX2lkGAIgASgJEiUKBWF0b21zGAMgAygLMhYuY2FtaW5vLkF0b21EZWZpbml0aW9uEi0KDGNvbmZvcm1hbmNlcxgEIAMoCzIXLmNhbWluby5BdG9tQ29uZm9ybWFuY2USJwoGc3RhdGVzGAUgAygLMhcuY2FtaW5vLlN0YXRlQXR0YWNobWVudBIlCgVlZGdlcxgGIAMoCzIWLmNhbWluby5FZGdlQXR0YWNobWVudCpoCgtDYXJkaW5hbGl0eRIbChdDQVJESU5BTElUWV9VTlNQRUNJRklFRBAAEhAKDE9QVElPTkFMX09ORRABEg8KC0VYQUNUTFlfT05FEAISCAoETUFOWRADEg8KC01BTllfVU5JUVVFEARiBnByb3RvMw"); /** * @generated from message camino.AtomDefinition @@ -47,6 +47,11 @@ export type AtomConformance = Message<"camino.AtomConformance"> & { * @generated from field: string interface_revision_id = 2; */ interfaceRevisionId: string; + + /** + * @generated from field: string conformance_id = 3; + */ + conformanceId: string; }; /** @@ -89,6 +94,11 @@ export type StateAttachment = Message<"camino.StateAttachment"> & { * @generated from field: string default_value_json = 6; */ defaultValueJson: string; + + /** + * @generated from field: string owner_conformance_id = 7; + */ + ownerConformanceId: string; }; /** @@ -155,6 +165,32 @@ export type EdgeEndpoint = Message<"camino.EdgeEndpoint"> & { * @generated from field: bool ordered = 5; */ ordered: boolean; + + /** + * Empty means restrict. Direction is the endpoint being deleted. + * + * @generated from field: string on_delete = 6; + */ + onDelete: string; + + /** + * @generated from field: bool retain_other = 7; + */ + retainOther: boolean; + + /** + * Empty for sets/lists, otherwise string, boolean, or int64 map keys. + * + * @generated from field: string key_type = 8; + */ + keyType: string; + + /** + * Explicit read-only dependency injection traversal, not mutation authority. + * + * @generated from field: bool public_traversal = 9; + */ + publicTraversal: boolean; }; /** @@ -187,6 +223,11 @@ export type EdgeAttachment = Message<"camino.EdgeAttachment"> & { * @generated from field: camino.EdgeEndpoint second = 4; */ second?: EdgeEndpoint | undefined; + + /** + * @generated from field: string owner_conformance_id = 5; + */ + ownerConformanceId: string; }; /** diff --git a/src/index.ts b/src/index.ts index 8031a5a..42b3113 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,12 @@ import http from "node:http"; +import { readFileSync } from "node:fs"; +import { createInvocationRegistry } from "./invocations.js"; +import { isObjectReference, referenceFromWire, referenceToWire, assertReferenceFree, type QxObjectRef } from "./references.js"; export * from "./bindings.js"; +export {relationshipMap, relationshipList, relationshipSet} from "./relationships.js"; import { AsyncLocalStorage } from "node:async_hooks"; -import { randomUUID } from "node:crypto"; +import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto"; +export {createMigrationContext, migrationObjectId, serveMigration, type MigrationContext, type MigrationInput, type MigrationOutput, type MigrationEdge} from "./migration.js"; import { create, equals } from "@bufbuild/protobuf"; import { Code, ConnectError, createClient, type Client, type ConnectRouter } from "@connectrpc/connect"; import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node"; @@ -61,10 +66,11 @@ const isWrappedValue = (value: unknown): value is { $quixosValue: Value } => isRecord(value) && "$quixosValue" in value && isRecord(value.$quixosValue) && value.$quixosValue.$typeName === "camino.Value"; -export const objectRef = (objectId: string) => ({ $quixosRef: objectId }); +export const objectRef = (reference: QxObjectRef) => { referenceToWire(reference); return reference; }; export const liveValue = (value: Value) => ({ $quixosValue: value }); export const jsToProtoValue = (value: unknown): Value => { + if (isObjectReference(value)) return create(ValueSchema, {kind: {case: "refValue", value: create(RefValueSchema, {objectId: referenceToWire(value)})}}); if (isWrappedValue(value)) return value.$quixosValue; if (value === null || value === undefined) { return create(ValueSchema, { kind: { case: "nullValue", value: create(NullValueSchema, {}) } }); @@ -79,11 +85,7 @@ export const jsToProtoValue = (value: unknown): Value => { kind: { case: "listValue", value: create(ListValueSchema, { values: value.map(jsToProtoValue) }) }, }); } - if (isRecord(value) && typeof value.$quixosRef === "string") { - return create(ValueSchema, { - kind: { case: "refValue", value: create(RefValueSchema, { objectId: value.$quixosRef }) }, - }); - } + if (isRecord(value) && "$quixosRef" in value) throw new Error("Raw ID wrappers are not object references"); if (isRecord(value) && typeof value.$quixosCrdtType === "string" && typeof value.$quixosCrdtPayload === "string") { return create(ValueSchema, { @@ -111,7 +113,7 @@ export const protoValueToJs = (value: Value | undefined): unknown => { case "stringValue": case "integerValue": return value.kind.value; case "bytesValue": return bytesToBase64(value.kind.value); - case "refValue": return value.kind.value.objectId; + case "refValue": return referenceFromWire(value.kind.value.objectId); case "listValue": return value.kind.value.values.map(protoValueToJs); case "objectValue": return Object.fromEntries( Object.entries(value.kind.value.fields).map(([key, entry]) => [key, protoValueToJs(entry)]), @@ -136,24 +138,31 @@ export type StatePort = { export type EdgePort = { edgeTypeId: string; projectionId: string; - resolve(): Promise; - connect(targetObjectId: string): Promise; - disconnect(targetObjectId: string): Promise; + resolve(): Promise; + connect(target: QxObjectRef): Promise; + disconnect(target: QxObjectRef): Promise; + collection(): Promise; + replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise; }; +export type RelationshipEntry = {edgeId?: string; target: T; key?: string | boolean | bigint}; +export type RelationshipCollection = {revision: bigint; entries: RelationshipEntry[]}; export type InterfacePort = { - objectId: string; + objectId: QxObjectRef; interfaceRevisionId: string; invoke(operationId: string, input?: Record): Promise; live(operationId: string, input?: Record): Promise>; }; export type ConstructorPort = { atomId: string; - construct(input?: Record): Promise; + construct(input?: Record): Promise; }; export type RuntimePort = StatePort | EdgePort | InterfacePort | ConstructorPort; export type RuntimeContext = { - objectId: string; + /** Cooperative cancellation. Completion is acknowledged only after the handler returns. */ + signal?: AbortSignal; + openSession?: () => Promise; + objectId: QxObjectRef; input: Record; inputProto: Record; ports: ReadonlyMap; @@ -163,6 +172,17 @@ export type RuntimeContext = { constructor(portId: string): ConstructorPort; }; +export type RuntimeSession = { + id: string; + run(work: (context: RuntimeContext) => Promise): Promise; + /** Close the external resource first, then close its host retention/session. */ + close(): Promise; +}; +export class RuntimeAuthorityError extends Error { + readonly retryable: boolean; + constructor(message: string) { super(message); this.name = "RuntimeAuthorityError"; this.retryable = /WORKSPACE_FENCED|STALE_EPOCH/.test(message); } +} + const targetForEdge = ( edge: { firstObjectId: string; secondObjectId: string; firstProjectionId: string }, projectionId: string, @@ -192,6 +212,7 @@ export const createRuntimeContext = ( return liveValue(value.value); }, async set(value) { + assertReferenceFree(isWrappedValue(value) ? protoValueToJs(value.$quixosValue) : value); await camino.writeState({ objectId: dependencyObjectId, slotId, value: jsToProtoValue(value) }); }, }; @@ -201,18 +222,34 @@ export const createRuntimeContext = ( case "edge": { const { edgeTypeId, projectionId } = dependency.binding.value; const dependencyObjectId = dependency.objectId || request.objectId; + const collectionResult = (response: {revision: bigint; entries: {edgeId: string; targetObjectId: string; key?: Value}[]}): RelationshipCollection => ({revision: response.revision, + entries: response.entries.map((entry) => ({edgeId: entry.edgeId, target: referenceFromWire(entry.targetObjectId), + ...(entry.key ? {key: entry.key.kind.case === "integerValue" ? BigInt(entry.key.kind.value) : protoValueToJs(entry.key) as string | boolean} : {})}))}); const edge: EdgePort = { edgeTypeId, projectionId, + async collection() { + await recordDependency({kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId}); + return collectionResult(await camino.readCollection({objectId: dependencyObjectId, edgeTypeId, projectionId})); + }, + async replace(entries, expectedRevision) { + return collectionResult(await camino.replaceCollection({objectId: dependencyObjectId, edgeTypeId, projectionId, expectedRevision, + entries: entries.map((entry) => { + assertReferenceFree(entry.key); + return {edgeId: entry.edgeId ?? "", targetObjectId: referenceToWire(entry.target), key: entry.key === undefined ? undefined : jsToProtoValue(entry.key)}; + })})); + }, async resolve() { await recordDependency({ kind: "edge", objectId: dependencyObjectId, attachmentId: edgeTypeId, projectionId }); const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId }); - return result.edges.map((entry) => targetForEdge(entry, projectionId)); + return result.edges.map((entry) => referenceFromWire(targetForEdge(entry, projectionId))); }, - async connect(targetObjectId) { + async connect(target) { + const targetObjectId = referenceToWire(target); await camino.connectEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId, targetObjectId }); }, - async disconnect(targetObjectId) { + async disconnect(target) { + const targetObjectId = referenceToWire(target); const result = await camino.resolveEdge({ objectId: dependencyObjectId, edgeTypeId, projectionId }); for (const entry of result.edges) { if (targetForEdge(entry, projectionId) === targetObjectId) await camino.disconnectEdge({ edgeId: entry.id }); @@ -251,7 +288,7 @@ export const createRuntimeContext = ( return response.result; }; const capability: InterfacePort = { - objectId: dependencyObjectId, + objectId: referenceFromWire(dependencyObjectId), interfaceRevisionId, async invoke(operationId, input = {}) { return protoValueToJs(await invoke(operationId, input)); @@ -275,7 +312,7 @@ export const createRuntimeContext = ( input: Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsToProtoValue(value)])), }); if (!response.object) throw new Error(`Constructor ${atomId} returned no object`); - return response.object.id; + return referenceFromWire(response.object.id); }, }; ports.set(dependency.portId, constructor); @@ -288,7 +325,7 @@ export const createRuntimeContext = ( return port as T; }; return { - objectId: request.objectId, + objectId: referenceFromWire(request.objectId), input: protoFieldsToJs(request.input), inputProto: request.input, ports, @@ -332,9 +369,12 @@ export const createPackageRuntimeRoutes = (config: { caminoUrl?: string; orchUrl?: string; }) => { + const invocations = createInvocationRegistry(); const headers: Record = {}; - if (process.env.CAMINO_RUNTIME_AUTH_TOKEN) { - headers["x-camino-runtime-token"] = process.env.CAMINO_RUNTIME_AUTH_TOKEN; + const processToken = process.env.CAMINO_RUNTIME_AUTH_TOKEN ?? (process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE + ? readFileSync(process.env.CAMINO_RUNTIME_AUTH_TOKEN_FILE, "utf8").trim() : ""); + if (processToken) { + headers["x-camino-runtime-token"] = processToken; } else if (process.env.CAMINO_RUNTIME_AUTH_REQUIRED === "1") { throw new Error("CAMINO_RUNTIME_AUTH_TOKEN is required"); } @@ -353,24 +393,114 @@ export const createPackageRuntimeRoutes = (config: { httpVersion: "1.1", })); + const authenticateInstance = (header: Headers) => { + if (!process.env.QUIXOS_RUNTIME_INSTANCE_ID) return; // standalone development ABI + const supplied = Buffer.from(header.get("x-quixos-instance-token") ?? ""); + const expected = Buffer.from(processToken); + if (!expected.length || supplied.length !== expected.length || !timingSafeEqual(supplied, expected)) { + throw new ConnectError("Invalid runtime instance credential", Code.Unauthenticated); + } + }; + const clientsFor = (request: { context?: { grant: string; instanceId: string; workspaceEpoch: string } }) => { + const context = request.context; + if (process.env.QUIXOS_RUNTIME_INSTANCE_ID && (!context?.grant || context.instanceId !== process.env.QUIXOS_RUNTIME_INSTANCE_ID || !context.workspaceEpoch)) { + throw new ConnectError("Managed invocation requires an exact instance and epoch grant", Code.Unauthenticated); + } + if (!context?.grant) return { camino, orch }; + const transport = (url: string) => createConnectTransport({ baseUrl: url, httpVersion: "1.1", interceptors: [(next) => async (call) => { + call.header.set("x-quixos-invocation-grant", context.grant); + call.header.set("x-camino-runtime-token", processToken); + return next(call); + }] }); + return { + camino: createClient(CaminoService, transport(config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310")), + orch: createClient(OrchestratorRuntime, transport(config.orchUrl ?? process.env.QUIXOS_ORCH_URL ?? "http://127.0.0.1:7311")), + }; + }; + const runtimeControl = async (operation: string, input: unknown): Promise => { + const response = await fetch(`${config.caminoUrl ?? process.env.CAMINO_URL ?? "http://127.0.0.1:7310"}/__runtime/${operation}`, { + method: "POST", headers: { "content-type": "application/json", "x-camino-runtime-token": processToken }, body: JSON.stringify(input), signal: AbortSignal.timeout(10_000), + }); + const value = await response.json() as T & {error?: string}; + if (!response.ok) throw new RuntimeAuthorityError(value.error ?? "Runtime authority request failed"); + return value; + }; + const attachSessions = (runtimeContext: RuntimeContext, request: RuntimeRequest & {context?: {grant: string; instanceId: string; workspaceEpoch: string; ownerConformanceId?: string}}) => { + if (!request.context?.grant || !request.context.ownerConformanceId) return; + runtimeContext.openSession = async () => { + const ownerId = request.context!.ownerConformanceId!; + const registration = { grant: request.context!.grant, objectId: request.objectId, ownerId, + sessionId: `session:${randomBytes(16).toString("hex")}`, token: randomBytes(32).toString("base64url") }; + const register = () => runtimeControl<{sessionId: string; token: string}>("register-session", registration); + const registered = await register().catch((error) => { + // Retry a transport/lost-response failure with exactly the same identity. + // Admission/authority errors are definitive and must not be retried here. + if (error instanceof RuntimeAuthorityError) throw error; + return register(); + }); + let closed = false; + return { + id: registered.sessionId, + async run(work) { + if (closed) throw new RuntimeAuthorityError("SESSION_CLOSED"); + // Acquisition happens before user code. A fence failure can be retried + // by the caller without replaying a side-effecting callback. + const grant = await runtimeControl<{grant: string; epoch: string; instanceId: string; invocationId: string; bindingDigest: string}>("acquire-session", registered); + const execution = invocations.begin(grant.invocationId); + const sessionRequest = { ...request, context: { grant: grant.grant, instanceId: grant.instanceId, workspaceEpoch: grant.epoch } }; + const clients = clientsFor(sessionRequest); + const context = createRuntimeContext(clients.camino, clients.orch, sessionRequest); + context.signal = execution.signal; + try { return await work(context); } + finally { + execution.finish(); + await runtimeControl("complete-invocation", { invocationId: grant.invocationId }).catch((error) => console.error("Session completion will be reconciled by the host", error)); + } + }, + async close() { await runtimeControl("close-session", registered); closed = true; }, + }; + }; + }; + return (router: ConnectRouter) => router.service(PackageRuntime, { - handshake: () => create(HandshakeResponseSchema, { + handshake: (request) => create(HandshakeResponseSchema, { packageRevisionId: config.packageRevisionId, runtimeProtocolVersion: "quixos-capabilities-v1", exportIds: Object.keys(config.exports), + capabilities: ["invocation-completion-v1", "instance-authentication-v1", "epoch-grants-v1"], + instanceId: process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "", + authenticationProof: request.nonce && processToken ? createHmac("sha256", processToken) + .update(JSON.stringify([request.nonce, process.env.QUIXOS_RUNTIME_INSTANCE_ID ?? "", config.packageRevisionId])) + .digest("hex") : "", }), - invoke: async (request) => { + getInvocationStatus: (request, context) => { + authenticateInstance(context.requestHeader); + return invocations.status(request.invocationId); + }, + cancelInvocation: (request, context) => { + authenticateInstance(context.requestHeader); + return invocations.cancel(request.invocationId); + }, + invoke: async (request, context) => { + authenticateInstance(context.requestHeader); + const { camino, orch } = clientsFor(request); const exportId = request.export?.exportId; const handler = exportId ? config.exports[exportId] : undefined; if (!handler) throw new ConnectError(`Unknown export ${exportId ?? ""}`, Code.NotFound); + const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID())); try { - const result = await evaluate(handler, createRuntimeContext(camino, orch, request)); + const runtimeContext = createRuntimeContext(camino, orch, request); + attachSessions(runtimeContext, request); + runtimeContext.signal = AbortSignal.any([context.signal, execution.signal]); + const result = await evaluate(handler, runtimeContext); + execution.finish(); return create(InvokeResponseSchema, { ok: true, result: result.value, dependencies: protoDependencies(result.dependencies), }); } catch (error) { + execution.finish(true); return create(InvokeResponseSchema, { ok: false, error: error instanceof Error ? error.message : String(error), @@ -378,13 +508,20 @@ export const createPackageRuntimeRoutes = (config: { } }, watch: async function* (request, context) { + authenticateInstance(context.requestHeader); + const { camino, orch } = clientsFor(request); const exportId = request.export?.exportId; const handler = exportId ? config.exports[exportId] : undefined; if (!handler || !isDerived(handler)) { throw new ConnectError(`Export ${exportId ?? ""} is not derived`, Code.FailedPrecondition); } + const execution = invocations.begin(request.invocationId || (process.env.QUIXOS_RUNTIME_INSTANCE_ID ? "" : randomUUID())); + const signal = AbortSignal.any([context.signal, execution.signal]); + try { const watchId = `watch:${randomUUID()}`; const runtimeContext = createRuntimeContext(camino, orch, request); + attachSessions(runtimeContext, request); + runtimeContext.signal = signal; type WatchOutcome = { key: string; done: boolean; error?: unknown }; type Subscription = { dependency: RuntimeDependency; @@ -404,7 +541,7 @@ export const createPackageRuntimeRoutes = (config: { const establish = (async () => { const controller = new AbortController(); const stream = camino.watchObject( - { objectId: dependency.objectId, includeSnapshot: true }, + { objectId: dependency.objectId, includeSnapshot: true, attachmentIds: request.context?.grant ? [dependency.attachmentId] : [] }, { signal: controller.signal }, )[Symbol.asyncIterator](); try { @@ -443,7 +580,7 @@ export const createPackageRuntimeRoutes = (config: { subscription.controller.abort(); } }; - context.signal.addEventListener("abort", abortAll, { once: true }); + signal.addEventListener("abort", abortAll, { once: true }); const evaluateWithStableSubscriptions = async () => { // A direct state/edge port records its dependency before reading it, @@ -459,6 +596,7 @@ export const createPackageRuntimeRoutes = (config: { throw new Error("Derived dependency discovery did not stabilize after 32 passes"); }; + try { let current = await evaluateWithStableSubscriptions(); yield create(WatchEventSchema, { watchId, @@ -468,11 +606,10 @@ export const createPackageRuntimeRoutes = (config: { }); const abort = new Promise<"abort">((resolve) => { - if (context.signal.aborted) resolve("abort"); - else context.signal.addEventListener("abort", () => resolve("abort"), { once: true }); + if (signal.aborted) resolve("abort"); + else signal.addEventListener("abort", () => resolve("abort"), { once: true }); }); - try { - while (!context.signal.aborted) { + while (!signal.aborted) { if (subscriptions.size === 0) { await abort; break; @@ -506,9 +643,10 @@ export const createPackageRuntimeRoutes = (config: { current = updated; } } finally { - context.signal.removeEventListener("abort", abortAll); + signal.removeEventListener("abort", abortAll); abortAll(); } + } finally { execution.finish(); } }, }); }; diff --git a/src/invocations.ts b/src/invocations.ts new file mode 100644 index 0000000..c78d9f1 --- /dev/null +++ b/src/invocations.ts @@ -0,0 +1,24 @@ +/** Execution completion, not HTTP disconnection, is the drain boundary. */ +export const createInvocationRegistry = () => { + const entries = new Map(); + return { + begin(id: string) { + if (!id || entries.has(id)) throw new Error("Invocation ID is missing or already used; invocations are never replayed implicitly"); + // Completed identities remain until process retirement. A bounded process + // may reject new work; it must not evict and accidentally replay a call. + if (entries.size >= 100_000) throw new Error("Invocation registry full; explicit runtime retirement required"); + const entry = { state: "running", controller: new AbortController() }; + entries.set(id, entry); + return { signal: entry.controller.signal, finish(failed = false) { entry.state = failed ? "failed" : "completed"; } }; + }, + status(id: string) { return { invocationId: id, state: entries.get(id)?.state ?? "unknown" }; }, + cancel(id: string) { + const entry = entries.get(id); + if (entry && ["running", "cancellation-requested"].includes(entry.state)) { + entry.state = "cancellation-requested"; + entry.controller.abort(); + } + return this.status(id); + }, + }; +}; diff --git a/src/migration.ts b/src/migration.ts new file mode 100644 index 0000000..338e78e --- /dev/null +++ b/src/migration.ts @@ -0,0 +1,95 @@ +import {createHash} from "node:crypto"; + +export type MigrationInput = { + schemaVersion: 1; executionId: string; exportId: string; + ports: {name: string; binding: string; view: "old" | "new"; access: ("read" | "write" | "create" | "edge")[]; atomId?: string; + attachedAtomId?: string; defaultValue?: unknown; + states?: {objectId: string; value: unknown}[]; edges?: MigrationEdge[]}[]; +}; +export type MigrationEdge = {id: string; edgeTypeId: string; firstObjectId: string; secondObjectId: string; firstProjectionId: string; secondProjectionId: string; firstOrdinal?: number; secondOrdinal?: number; firstKeyJson?: string; secondKeyJson?: string}; +export type MigrationOutput = {schemaVersion: 1; executionId: string; + writes: {port: string; objectId: string; value: unknown}[]; + creates: {port: string; logicalKey: string; objectId: string}[]; + edgeReplacements: {port: string; edges: MigrationEdge[]}[]}; +export type MigrationContext = { + enumerate(port: string): {objectId: string; value: unknown}[]; + read(port: string, objectId: string): unknown; + write(port: string, objectId: string, value: unknown): void; + create(port: string, logicalKey: string): string; + edges(port: string): MigrationEdge[]; + replaceEdges(port: string, edges: MigrationEdge[]): void; +}; +export const migrationObjectId = (executionId: string, port: string, logicalKey: string) => + `obj:migration:${createHash("sha256").update(JSON.stringify([executionId, port, logicalKey])).digest("hex")}`; + +/** No ordinary RuntimeContext or network/database clients are supplied here. + * Process isolation belongs to the host, not this convenience API. */ +export const createMigrationContext = (input: MigrationInput) => { + if (input.schemaVersion !== 1 || !input.executionId || new Set(input.ports.map((entry) => entry.name)).size !== input.ports.length) throw new Error("Invalid migration input"); + const output: MigrationOutput = {schemaVersion: 1, executionId: input.executionId, writes: [], creates: [], edgeReplacements: []}; + const port = (name: string, access: string) => { + const selected = input.ports.find((entry) => entry.name === name); + if (!selected?.access.includes(access as "read") || (selected.view === "old" && access !== "read")) throw new Error(`Migration port ${name} does not grant ${access}`); + return selected; + }; + const context: MigrationContext = { + enumerate(name) { + const selected = port(name, "read"), states = structuredClone(selected.states ?? []); + if (selected.view === "new" && Object.hasOwn(selected, "defaultValue")) for (const helper of output.creates) { + if (input.ports.find((entry) => entry.name === helper.port)?.atomId === selected.attachedAtomId && !states.some((entry) => entry.objectId === helper.objectId)) states.push({objectId: helper.objectId, value: structuredClone(selected.defaultValue)}); + } + if (selected.view === "new") for (const write of output.writes) { + if (input.ports.find((entry) => entry.name === write.port)?.binding !== selected.binding) continue; + const existing = states.findIndex((entry) => entry.objectId === write.objectId), entry = {objectId: write.objectId, value: structuredClone(write.value)}; + if (existing < 0) states.push(entry); else states[existing] = entry; + } + return states.sort((a, b) => a.objectId < b.objectId ? -1 : a.objectId > b.objectId ? 1 : 0); + }, + read(name, objectId) {return context.enumerate(name).find((entry) => entry.objectId === objectId)?.value;}, + write(name, objectId, value) { + port(name, "write"); + const previous = output.writes.findIndex((entry) => entry.port === name && entry.objectId === objectId); + const entry = {port: name, objectId, value: structuredClone(value)}; + if (previous < 0) output.writes.push(entry); else output.writes[previous] = entry; + }, + create(name, logicalKey) { + port(name, "create"); + if (!logicalKey || logicalKey.length > 1024) throw new Error("Migration creation requires a bounded stable logical key"); + const objectId = migrationObjectId(input.executionId, name, logicalKey); + if (!output.creates.some((entry) => entry.objectId === objectId)) output.creates.push({port: name, logicalKey, objectId}); + return objectId; + }, + edges(name) { + const selected = port(name, "read"); + const replacement = selected.view === "new" ? output.edgeReplacements.find((entry) => input.ports.find((candidate) => candidate.name === entry.port)?.binding === selected.binding) : undefined; + return structuredClone(replacement?.edges ?? selected.edges ?? []); + }, + replaceEdges(name, edges) { + port(name, "edge"); + const previous = output.edgeReplacements.findIndex((entry) => entry.port === name); + const entry = {port: name, edges: structuredClone(edges)}; + if (previous < 0) output.edgeReplacements.push(entry); else output.edgeReplacements[previous] = entry; + }, + }; + return {context, result: () => structuredClone(output)}; +}; + +/** Entrypoint for an immutable package's dedicated bin/migrate executable. + * stdout is protocol-only; send diagnostics to stderr. The host independently + * validates every write, helper identity, contract, and completion receipt. */ +export const serveMigration = async (exports: Record void | Promise>) => { + const chunks: Buffer[] = []; let bytes = 0; + for await (const chunk of process.stdin) { + bytes += chunk.length; + if (bytes > 16 * 1024 * 1024) throw new Error("Migration input exceeds 16 MiB"); + chunks.push(Buffer.from(chunk)); + } + const input = JSON.parse(Buffer.concat(chunks).toString("utf8")) as MigrationInput; + const implementation = Object.hasOwn(exports, input.exportId) ? exports[input.exportId] : undefined; + if (!implementation) throw new Error("Unknown migration export"); + const execution = createMigrationContext(input); + await implementation(execution.context); + const result = JSON.stringify(execution.result()); + if (Buffer.byteLength(result) > 16 * 1024 * 1024) throw new Error("Migration output exceeds 16 MiB"); + process.stdout.write(`${result}\n`); +}; diff --git a/src/quixos/orch_pb.ts b/src/quixos/orch_pb.ts index 8c0dd48..01117f0 100644 --- a/src/quixos/orch_pb.ts +++ b/src/quixos/orch_pb.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/orch.proto (package quixos.orch, syntax proto3) /* eslint-disable */ diff --git a/src/quixos/package_pb.ts b/src/quixos/package_pb.ts index 428c66f..7c96df3 100644 --- a/src/quixos/package_pb.ts +++ b/src/quixos/package_pb.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/package.proto (package quixos, syntax proto3) /* eslint-disable */ diff --git a/src/quixos/refs_pb.ts b/src/quixos/refs_pb.ts index 0b0ce7b..bdc9302 100644 --- a/src/quixos/refs_pb.ts +++ b/src/quixos/refs_pb.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/refs.proto (package quixos, syntax proto3) /* eslint-disable */ diff --git a/src/quixos/runtime_pb.ts b/src/quixos/runtime_pb.ts index 33e0dbd..6d3b546 100644 --- a/src/quixos/runtime_pb.ts +++ b/src/quixos/runtime_pb.ts @@ -1,4 +1,4 @@ -// @generated by protoc-gen-es v2.12.1 with parameter "target=ts,import_extension=js" +// @generated by protoc-gen-es v2.14.1 with parameter "target=ts,import_extension=js" // @generated from file quixos/runtime.proto (package quixos.runtime, syntax proto3) /* eslint-disable */ @@ -14,7 +14,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file quixos/runtime.proto. */ export const file_quixos_runtime: GenFile = /*@__PURE__*/ - fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiMQoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkiZgoRSGFuZHNoYWtlUmVzcG9uc2USGwoTcGFja2FnZV9yZXZpc2lvbl9pZBgBIAEoCRIgChhydW50aW1lX3Byb3RvY29sX3ZlcnNpb24YAiABKAkSEgoKZXhwb3J0X2lkcxgDIAMoCSKLAgoNSW52b2tlUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI3CgVpbnB1dBgEIAMoCzIoLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASKDAQoOSW52b2tlUmVzcG9uc2USCgoCb2sYASABKAgSHQoGcmVzdWx0GAIgASgLMg0uY2FtaW5vLlZhbHVlEg0KBWVycm9yGAMgASgJEjcKDGRlcGVuZGVuY2llcxgEIAMoCzIhLnF1aXhvcy5ydW50aW1lLkRlcml2ZWREZXBlbmRlbmN5IokCCgxXYXRjaFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNgoFaW5wdXQYBCADKAsyJy5xdWl4b3MucnVudGltZS5XYXRjaFJlcXVlc3QuSW5wdXRFbnRyeRIwCgxkZXBlbmRlbmNpZXMYBSADKAsyGi5xdWl4b3MuSW5qZWN0ZWREZXBlbmRlbmN5GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDLwAQoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwAWIGcHJvdG8z", [file_camino_api, file_quixos_refs]); + fileDesc("ChRxdWl4b3MvcnVudGltZS5wcm90bxIOcXVpeG9zLnJ1bnRpbWUiQAoQSGFuZHNoYWtlUmVxdWVzdBIdChVvcmNoX3Byb3RvY29sX3ZlcnNpb24YASABKAkSDQoFbm9uY2UYAiABKAkirwEKEUhhbmRzaGFrZVJlc3BvbnNlEhsKE3BhY2thZ2VfcmV2aXNpb25faWQYASABKAkSIAoYcnVudGltZV9wcm90b2NvbF92ZXJzaW9uGAIgASgJEhIKCmV4cG9ydF9pZHMYAyADKAkSEwoLaW5zdGFuY2VfaWQYBCABKAkSHAoUYXV0aGVudGljYXRpb25fcHJvb2YYBSABKAkSFAoMY2FwYWJpbGl0aWVzGAYgAygJIpoBChFJbnZvY2F0aW9uQ29udGV4dBIXCg93b3Jrc3BhY2VfZXBvY2gYASABKAkSEwoLaW5zdGFuY2VfaWQYAiABKAkSFgoOYmluZGluZ19kaWdlc3QYAyABKAkSDQoFZ3JhbnQYBCABKAkSEgoKc2Vzc2lvbl9pZBgFIAEoCRIcChRvd25lcl9jb25mb3JtYW5jZV9pZBgGIAEoCSIxChhJbnZvY2F0aW9uQ29udHJvbFJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCSI4ChBJbnZvY2F0aW9uU3RhdHVzEhUKDWludm9jYXRpb25faWQYASABKAkSDQoFc3RhdGUYAiABKAkivwIKDUludm9rZVJlcXVlc3QSFQoNaW52b2NhdGlvbl9pZBgBIAEoCRIoCgZleHBvcnQYAiABKAsyGC5xdWl4b3MuUGFja2FnZUV4cG9ydFJlZhIRCglvYmplY3RfaWQYAyABKAkSNwoFaW5wdXQYBCADKAsyKC5xdWl4b3MucnVudGltZS5JbnZva2VSZXF1ZXN0LklucHV0RW50cnkSMAoMZGVwZW5kZW5jaWVzGAUgAygLMhoucXVpeG9zLkluamVjdGVkRGVwZW5kZW5jeRIyCgdjb250ZXh0GAYgASgLMiEucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRleHQaOwoKSW5wdXRFbnRyeRILCgNrZXkYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWU6AjgBIoMBCg5JbnZva2VSZXNwb25zZRIKCgJvaxgBIAEoCBIdCgZyZXN1bHQYAiABKAsyDS5jYW1pbm8uVmFsdWUSDQoFZXJyb3IYAyABKAkSNwoMZGVwZW5kZW5jaWVzGAQgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kivQIKDFdhdGNoUmVxdWVzdBIVCg1pbnZvY2F0aW9uX2lkGAEgASgJEigKBmV4cG9ydBgCIAEoCzIYLnF1aXhvcy5QYWNrYWdlRXhwb3J0UmVmEhEKCW9iamVjdF9pZBgDIAEoCRI2CgVpbnB1dBgEIAMoCzInLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdC5JbnB1dEVudHJ5EjAKDGRlcGVuZGVuY2llcxgFIAMoCzIaLnF1aXhvcy5JbmplY3RlZERlcGVuZGVuY3kSMgoHY29udGV4dBgGIAEoCzIhLnF1aXhvcy5ydW50aW1lLkludm9jYXRpb25Db250ZXh0GjsKCklucHV0RW50cnkSCwoDa2V5GAEgASgJEhwKBXZhbHVlGAIgASgLMg0uY2FtaW5vLlZhbHVlOgI4ASJiChFEZXJpdmVkRGVwZW5kZW5jeRIMCgRraW5kGAEgASgJEhEKCW9iamVjdF9pZBgCIAEoCRIVCg1hdHRhY2htZW50X2lkGAMgASgJEhUKDXByb2plY3Rpb25faWQYBCABKAkilQEKCldhdGNoRXZlbnQSEAoId2F0Y2hfaWQYASABKAkSHAoFdmFsdWUYAiABKAsyDS5jYW1pbm8uVmFsdWUSNwoMZGVwZW5kZW5jaWVzGAMgAygLMiEucXVpeG9zLnJ1bnRpbWUuRGVyaXZlZERlcGVuZGVuY3kSDQoFZXJyb3IYBCABKAkSDwoHaW5pdGlhbBgFIAEoCDKzAwoOUGFja2FnZVJ1bnRpbWUSUAoJSGFuZHNoYWtlEiAucXVpeG9zLnJ1bnRpbWUuSGFuZHNoYWtlUmVxdWVzdBohLnF1aXhvcy5ydW50aW1lLkhhbmRzaGFrZVJlc3BvbnNlEkcKBkludm9rZRIdLnF1aXhvcy5ydW50aW1lLkludm9rZVJlcXVlc3QaHi5xdWl4b3MucnVudGltZS5JbnZva2VSZXNwb25zZRJDCgVXYXRjaBIcLnF1aXhvcy5ydW50aW1lLldhdGNoUmVxdWVzdBoaLnF1aXhvcy5ydW50aW1lLldhdGNoRXZlbnQwARJhChNHZXRJbnZvY2F0aW9uU3RhdHVzEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1cxJeChBDYW5jZWxJbnZvY2F0aW9uEigucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvbkNvbnRyb2xSZXF1ZXN0GiAucXVpeG9zLnJ1bnRpbWUuSW52b2NhdGlvblN0YXR1c2IGcHJvdG8z", [file_camino_api, file_quixos_refs]); /** * @generated from message quixos.runtime.HandshakeRequest @@ -24,6 +24,11 @@ export type HandshakeRequest = Message<"quixos.runtime.HandshakeRequest"> & { * @generated from field: string orch_protocol_version = 1; */ orchProtocolVersion: string; + + /** + * @generated from field: string nonce = 2; + */ + nonce: string; }; /** @@ -51,6 +56,21 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & { * @generated from field: repeated string export_ids = 3; */ exportIds: string[]; + + /** + * @generated from field: string instance_id = 4; + */ + instanceId: string; + + /** + * @generated from field: string authentication_proof = 5; + */ + authenticationProof: string; + + /** + * @generated from field: repeated string capabilities = 6; + */ + capabilities: string[]; }; /** @@ -60,6 +80,91 @@ export type HandshakeResponse = Message<"quixos.runtime.HandshakeResponse"> & { export const HandshakeResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_quixos_runtime, 1); +/** + * @generated from message quixos.runtime.InvocationContext + */ +export type InvocationContext = Message<"quixos.runtime.InvocationContext"> & { + /** + * @generated from field: string workspace_epoch = 1; + */ + workspaceEpoch: string; + + /** + * @generated from field: string instance_id = 2; + */ + instanceId: string; + + /** + * @generated from field: string binding_digest = 3; + */ + bindingDigest: string; + + /** + * @generated from field: string grant = 4; + */ + grant: string; + + /** + * @generated from field: string session_id = 5; + */ + sessionId: string; + + /** + * Host-selected owner; packages must not invent workspace-local ownership. + * + * @generated from field: string owner_conformance_id = 6; + */ + ownerConformanceId: string; +}; + +/** + * Describes the message quixos.runtime.InvocationContext. + * Use `create(InvocationContextSchema)` to create a new message. + */ +export const InvocationContextSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_quixos_runtime, 2); + +/** + * @generated from message quixos.runtime.InvocationControlRequest + */ +export type InvocationControlRequest = Message<"quixos.runtime.InvocationControlRequest"> & { + /** + * @generated from field: string invocation_id = 1; + */ + invocationId: string; +}; + +/** + * Describes the message quixos.runtime.InvocationControlRequest. + * Use `create(InvocationControlRequestSchema)` to create a new message. + */ +export const InvocationControlRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_quixos_runtime, 3); + +/** + * @generated from message quixos.runtime.InvocationStatus + */ +export type InvocationStatus = Message<"quixos.runtime.InvocationStatus"> & { + /** + * @generated from field: string invocation_id = 1; + */ + invocationId: string; + + /** + * unknown, running, cancellation-requested, completed, failed + * + * @generated from field: string state = 2; + */ + state: string; +}; + +/** + * Describes the message quixos.runtime.InvocationStatus. + * Use `create(InvocationStatusSchema)` to create a new message. + */ +export const InvocationStatusSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_quixos_runtime, 4); + /** * @generated from message quixos.runtime.InvokeRequest */ @@ -88,6 +193,11 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & { * @generated from field: repeated quixos.InjectedDependency dependencies = 5; */ dependencies: InjectedDependency[]; + + /** + * @generated from field: quixos.runtime.InvocationContext context = 6; + */ + context?: InvocationContext | undefined; }; /** @@ -95,7 +205,7 @@ export type InvokeRequest = Message<"quixos.runtime.InvokeRequest"> & { * Use `create(InvokeRequestSchema)` to create a new message. */ export const InvokeRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_quixos_runtime, 2); + messageDesc(file_quixos_runtime, 5); /** * @generated from message quixos.runtime.InvokeResponse @@ -127,7 +237,7 @@ export type InvokeResponse = Message<"quixos.runtime.InvokeResponse"> & { * Use `create(InvokeResponseSchema)` to create a new message. */ export const InvokeResponseSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_quixos_runtime, 3); + messageDesc(file_quixos_runtime, 6); /** * @generated from message quixos.runtime.WatchRequest @@ -157,6 +267,11 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & { * @generated from field: repeated quixos.InjectedDependency dependencies = 5; */ dependencies: InjectedDependency[]; + + /** + * @generated from field: quixos.runtime.InvocationContext context = 6; + */ + context?: InvocationContext | undefined; }; /** @@ -164,7 +279,7 @@ export type WatchRequest = Message<"quixos.runtime.WatchRequest"> & { * Use `create(WatchRequestSchema)` to create a new message. */ export const WatchRequestSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_quixos_runtime, 4); + messageDesc(file_quixos_runtime, 7); /** * @generated from message quixos.runtime.DerivedDependency @@ -196,7 +311,7 @@ export type DerivedDependency = Message<"quixos.runtime.DerivedDependency"> & { * Use `create(DerivedDependencySchema)` to create a new message. */ export const DerivedDependencySchema: GenMessage = /*@__PURE__*/ - messageDesc(file_quixos_runtime, 5); + messageDesc(file_quixos_runtime, 8); /** * @generated from message quixos.runtime.WatchEvent @@ -233,7 +348,7 @@ export type WatchEvent = Message<"quixos.runtime.WatchEvent"> & { * Use `create(WatchEventSchema)` to create a new message. */ export const WatchEventSchema: GenMessage = /*@__PURE__*/ - messageDesc(file_quixos_runtime, 6); + messageDesc(file_quixos_runtime, 9); /** * @generated from service quixos.runtime.PackageRuntime @@ -263,6 +378,22 @@ export const PackageRuntime: GenService<{ input: typeof WatchRequestSchema; output: typeof WatchEventSchema; }, + /** + * @generated from rpc quixos.runtime.PackageRuntime.GetInvocationStatus + */ + getInvocationStatus: { + methodKind: "unary"; + input: typeof InvocationControlRequestSchema; + output: typeof InvocationStatusSchema; + }, + /** + * @generated from rpc quixos.runtime.PackageRuntime.CancelInvocation + */ + cancelInvocation: { + methodKind: "unary"; + input: typeof InvocationControlRequestSchema; + output: typeof InvocationStatusSchema; + }, }> = /*@__PURE__*/ serviceDesc(file_quixos_runtime, 0); diff --git a/src/references.ts b/src/references.ts new file mode 100644 index 0000000..66af0ff --- /dev/null +++ b/src/references.ts @@ -0,0 +1,35 @@ +/** Opaque runtime identity. The wire codec, never ordinary package state, owns + * the raw ID. These handles do not themselves confer authority or a lease. */ +const identities = new WeakMap(); +declare const referenceBrand: unique symbol; +export interface QxObjectRef { + readonly [referenceBrand]: {readonly [K in Identity]: true}; + equals(other: QxObjectRef): boolean; +} +class Reference { + constructor(id: string) { identities.set(this, id); Object.freeze(this); } + equals(other: unknown) { return isObjectReference(other) && identities.get(this) === identities.get(other); } + toJSON(): never { throw new Error("Object references cannot be serialized into ordinary data"); } + toString(): never { throw new Error("Object references cannot be coerced to strings"); } + [Symbol.toPrimitive](): never { throw new Error("Object references cannot be coerced to scalar values"); } +} +export const isObjectReference = (value: unknown): value is QxObjectRef => + typeof value === "object" && value !== null && identities.has(value); + +/** Internal transport boundary; intentionally not exported from the SDK entry. */ +export const referenceFromWire = (id: string): QxObjectRef => { + if (typeof id !== "string" || !id) throw new Error("Missing object reference identity"); + return new Reference(id) as unknown as QxObjectRef; +}; +export const referenceToWire = (value: unknown): string => { + if (!isObjectReference(value)) throw new Error("Expected an opaque object reference, not a raw ID"); + return identities.get(value)!; +}; +export const assertReferenceFree = (value: unknown, seen = new Set()): void => { + if (!value || typeof value !== "object") return; + if (isObjectReference(value)) throw new Error("Managed references belong in declared RPC references or graph relationships, not ordinary state/messages"); + if (seen.has(value)) throw new Error("Cyclic ordinary data"); + seen.add(value); + if (!(value instanceof Uint8Array)) for (const child of Object.values(value)) assertReferenceFree(child, seen); + seen.delete(value); +}; diff --git a/src/relationships.ts b/src/relationships.ts new file mode 100644 index 0000000..79670bc --- /dev/null +++ b/src/relationships.ts @@ -0,0 +1,59 @@ +import type {QxObjectRef} from "./references.js"; +import type {RelationshipCollection, RelationshipEntry} from "./index.js"; +type Key = string | boolean | bigint; +type Port = {collection(): Promise>; replace(entries: RelationshipEntry[], expectedRevision: bigint): Promise>}; +const checked = async (port: Port, revision: bigint) => { + const snapshot = await port.collection(); + if (snapshot.revision !== revision) throw new Error("STALE_COLLECTION_REVISION"); + return snapshot; +}; +/** Helpers never retry a failed CAS or silently overwrite concurrent edits. */ +export const relationshipMap = (port: Port) => ({ + read: () => port.collection(), + async get(key: K) {const snapshot = await port.collection(); return {revision: snapshot.revision, value: snapshot.entries.find((entry) => entry.key === key)?.target};}, + async set(key: K, target: T, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + const entries = snapshot.entries.filter((entry) => entry.key !== key); + const existing = snapshot.entries.find((entry) => entry.key === key && entry.target.equals(target)); + entries.push(existing ?? {key, target}); + return port.replace(entries, expectedRevision); + }, + async delete(key: K, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + return port.replace(snapshot.entries.filter((entry) => entry.key !== key), expectedRevision); + }, +}); +export const relationshipList = (port: Port) => ({ + read: () => port.collection(), + async insert(index: number, target: T, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + if (!Number.isSafeInteger(index) || index < 0 || index > snapshot.entries.length) throw new Error("List index out of bounds"); + snapshot.entries.splice(index, 0, {target}); + return port.replace(snapshot.entries, expectedRevision); + }, + async move(edgeId: string, index: number, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + const prior = snapshot.entries.findIndex((entry) => entry.edgeId === edgeId); + if (prior < 0 || !Number.isSafeInteger(index) || index < 0 || index >= snapshot.entries.length) throw new Error("Unknown list entry or invalid index"); + const [entry] = snapshot.entries.splice(prior, 1); + snapshot.entries.splice(index, 0, entry); + return port.replace(snapshot.entries, expectedRevision); + }, + async delete(edgeId: string, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + if (!snapshot.entries.some((entry) => entry.edgeId === edgeId)) throw new Error("Unknown list entry"); + return port.replace(snapshot.entries.filter((entry) => entry.edgeId !== edgeId), expectedRevision); + }, +}); +export const relationshipSet = (port: Port) => ({ + read: () => port.collection(), + async add(target: T, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + if (snapshot.entries.some((entry) => entry.target.equals(target))) return snapshot; + return port.replace([...snapshot.entries, {target}], expectedRevision); + }, + async delete(target: T, expectedRevision: bigint) { + const snapshot = await checked(port, expectedRevision); + return port.replace(snapshot.entries.filter((entry) => !entry.target.equals(target)), expectedRevision); + }, +}); diff --git a/test/bindings.test.mjs b/test/bindings.test.mjs index 90fd74e..953fdd8 100644 --- a/test/bindings.test.mjs +++ b/test/bindings.test.mjs @@ -1,15 +1,52 @@ import assert from "node:assert/strict"; import test from "node:test"; +import { referenceFromWire } from "../dist/references.js"; import { bindQxHandler, decodeQxValue, encodeQxValue, jsToProtoValue, liveValue, protoValueToJs } from "../dist/index.js"; const scalar = (name) => ({ kind: "scalar", name }); const unit = { kind: "builtin", name: "unit" }; +test("typed sessions rebind ports and cancellation to each acquired invocation", async () => { + const first = new AbortController(), second = new AbortController(); + let closed = false; + const context = (value, signal) => ({objectId: referenceFromWire("obj:owner"), inputProto: {}, signal, + state: () => ({live: async () => liveValue(jsToProtoValue(value))})}); + const raw = {...context(1n, first.signal), openSession: async () => ({id: "session:test", + run: (work) => work(context(2n, second.signal)), close: async () => {closed = true;}})}; + const handler = bindQxHandler({inputType: unit, outputType: unit, ports: {counter: {kind: "state", id: "counter", valueType: scalar("int64"), primitives: ["read"]}}}, async (bound) => { + assert.equal(bound.signal, first.signal); + const session = await bound.openSession(); + await session.run(async (next) => { + assert.equal(next.signal, second.signal); + assert.equal(await next.ports.counter.get(), 2n); + assert.equal(next.openSession, undefined); + }); + await session.close(); + }, {}); + await handler(raw); + assert.equal(closed, true); +}); test("binding codecs round trip nested bytes, 64-bit integers, nulls, and references", () => { const values = [[scalar("int64"), -(2n ** 63n)], [scalar("uint64"), 2n ** 64n - 1n], [scalar("bytes"), new Uint8Array([0, 255])], [{ kind: "list", value: { kind: "optional", value: scalar("int64") } }, [null, 2n ** 60n]], - [{ kind: "object-ref", expectation: { kind: "atom", atomId: "thing" } }, "obj:thing"]]; + [{ kind: "object-ref", expectation: { kind: "atom", atomId: "thing" } }, referenceFromWire("obj:thing")]]; for (const [type, value] of values) assert.deepEqual(decodeQxValue(type, encodeQxValue(type, value, {}), {}), value); }); + +test("opaque references pass declared RPC boundaries but cannot enter ordinary data", () => { + const reference = referenceFromWire("obj:thing"); + const type = {kind: "object-ref", expectation: {kind: "atom", atomId: "thing"}}; + const roundtrip = decodeQxValue(type, encodeQxValue(type, reference, {}), {}); + assert.equal(reference.equals(roundtrip), true); + assert.equal(reference.equals(referenceFromWire("obj:other")), false); + assert.throws(() => JSON.stringify({nested: [reference]}), /cannot be serialized/); + assert.throws(() => String(reference), /cannot be coerced/); + assert.throws(() => encodeQxValue(type, "obj:thing", {}), /opaque/); + assert.throws(() => encodeQxValue(scalar("string"), reference, {}), /Managed references/); + const message = {kind: "message", descriptorId: "Payload"}; + assert.throws(() => encodeQxValue(message, {nested: reference}, {Payload: {encode: jsToProtoValue}}), /Managed references/); + assert.throws(() => encodeQxValue(message, {}, {Payload: {encode: () => jsToProtoValue(reference)}}), /Managed references/); + assert.throws(() => decodeQxValue(message, jsToProtoValue(reference), {Payload: {decode: () => ({})}}), /Managed references/); +}); test("typed state and interface ports preserve declared values and exact operation IDs", async () => { const spec = { inputType: scalar("int64"), outputType: scalar("bytes"), ports: { data: { kind: "state", id: "state-id", valueType: scalar("int64"), primitives: ["read", "write"] }, diff --git a/test/invocations.test.mjs b/test/invocations.test.mjs new file mode 100644 index 0000000..db8bf14 --- /dev/null +++ b/test/invocations.test.mjs @@ -0,0 +1,15 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { createInvocationRegistry } from "../dist/invocations.js"; + +test("cancel requests do not acknowledge execution completion or allow replay", () => { + const registry = createInvocationRegistry(); + const execution = registry.begin("call-1"); + assert.equal(registry.cancel("call-1").state, "cancellation-requested"); + assert.equal(execution.signal.aborted, true); + assert.equal(registry.status("call-1").state, "cancellation-requested"); + execution.finish(); + assert.equal(registry.status("call-1").state, "completed"); + assert.throws(() => registry.begin("call-1"), /already used/); + assert.equal(registry.status("missing").state, "unknown"); +}); diff --git a/test/migration.test.mjs b/test/migration.test.mjs new file mode 100644 index 0000000..39e0a83 --- /dev/null +++ b/test/migration.test.mjs @@ -0,0 +1,24 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import {createMigrationContext, migrationObjectId} from "../dist/migration.js"; +test("migration context offers restricted ports and deterministic helper identities", () => { + const input = {schemaVersion: 1, executionId: "operation:transition", exportId: "migrate", ports: [ + {name: "old", binding: "slot:name", view: "old", access: ["read"], states: [{objectId: "obj:one", value: "Alice"}]}, + {name: "new", binding: "slot:name", view: "new", access: ["write"]}, {name: "newRead", binding: "slot:name", view: "new", access: ["read"]}, + {name: "helpers", binding: "atom:helper", view: "new", access: ["create"]}, + ]}; + const {context, result} = createMigrationContext(input); + assert.equal(context.read("old", "obj:one"), "Alice"); + assert.throws(() => context.write("old", "obj:one", "Bob"), /does not grant/); + assert.throws(() => context.read("new", "obj:one"), /does not grant/); + context.write("new", "obj:one", "Alice"); + assert.equal(context.read("newRead", "obj:one"), "Alice"); + context.write("new", "obj:one", "Bob"); + assert.equal(context.read("newRead", "obj:one"), "Bob"); + assert.equal(context.read("old", "obj:one"), "Alice"); + const helper = context.create("helpers", "one"); + assert.equal(helper, migrationObjectId(input.executionId, "helpers", "one")); + assert.equal(context.create("helpers", "one"), helper); + assert.equal(result().creates.length, 1); + assert.deepEqual(input.ports[0].states, [{objectId: "obj:one", value: "Alice"}]); +}); diff --git a/test/relationships.test.mjs b/test/relationships.test.mjs new file mode 100644 index 0000000..87e0739 --- /dev/null +++ b/test/relationships.test.mjs @@ -0,0 +1,27 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import {relationshipMap, relationshipList, relationshipSet} from "../dist/index.js"; +import {referenceFromWire} from "../dist/references.js"; +test("relationship helpers preserve handles and require explicit collection revisions", async () => { + let current = {revision: 0n, entries: []}, serial = 0; + const port = {collection: async () => ({revision: current.revision, entries: current.entries.map((entry) => ({...entry}))}), + replace: async (entries, revision) => { + assert.equal(revision, current.revision); + current = {revision: revision + 1n, entries: entries.map((entry) => ({...entry, edgeId: entry.edgeId ?? `edge:${++serial}`}))}; + return port.collection(); + }}; + const a = referenceFromWire("obj:a"), b = referenceFromWire("obj:b"); + const map = relationshipMap(port); + await map.set("a1", a, 0n); + assert.equal((await map.get("a1")).value.equals(a), true); + await assert.rejects(() => map.set("b1", b, 0n), /STALE_COLLECTION/); + await map.delete("a1", 1n); + const list = relationshipList(port); + const inserted = await list.insert(0, a, 2n); + await list.insert(1, b, 3n); + const moved = await list.move(inserted.entries[0].edgeId, 1, 4n); + assert.equal(moved.entries[1].target.equals(a), true); + const set = relationshipSet(port); + const unchanged = await set.add(referenceFromWire("obj:a"), 5n); + assert.equal(unchanged.revision, 5n); +}); diff --git a/test/runtime.test.mjs b/test/runtime.test.mjs index 94045a0..39bea4b 100644 --- a/test/runtime.test.mjs +++ b/test/runtime.test.mjs @@ -1,6 +1,7 @@ import assert from "node:assert/strict"; import http from "node:http"; import test from "node:test"; +import { referenceFromWire } from "../dist/references.js"; import { create } from "@bufbuild/protobuf"; import { createClient } from "@connectrpc/connect"; import { connectNodeAdapter, createConnectTransport } from "@connectrpc/connect-node"; @@ -45,12 +46,12 @@ const listen = async (routes) => { test("generic values preserve nested values and object references", () => { const value = jsToProtoValue({ title: "A task", - target: { $quixosRef: "obj:target" }, + target: referenceFromWire("obj:target"), tags: ["one", "two"], }); assert.deepEqual(protoValueToJs(value), { title: "A task", - target: "obj:target", + target: referenceFromWire("obj:target"), tags: ["one", "two"], }); });