@lssm/lib.contracts 0.0.0-canary-20251220041653 → 0.0.0-canary-20251221132705

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/README.md +4 -4
  2. package/dist/_virtual/rolldown_runtime.js +37 -0
  3. package/dist/app-config/contracts.d.ts +60 -60
  4. package/dist/app-config/contracts.js +1 -1
  5. package/dist/app-config/events.d.ts +27 -27
  6. package/dist/app-config/lifecycle-contracts.d.ts +90 -90
  7. package/dist/app-config/lifecycle-contracts.js +1 -1
  8. package/dist/data-views.d.ts +11 -0
  9. package/dist/data-views.js +26 -0
  10. package/dist/docs/tech/contracts/README.docblock.js +2 -2
  11. package/dist/docs/tech/contracts/openapi-export.docblock.js +6 -6
  12. package/dist/docs/tech/contracts/ops-to-presentation-linking.docblock.js +2 -2
  13. package/dist/docs/tech/contracts/tests.docblock.js +2 -2
  14. package/dist/experiments/spec-resolver.d.ts +2 -2
  15. package/dist/features.d.ts +16 -5
  16. package/dist/features.js +26 -0
  17. package/dist/forms.d.ts +11 -0
  18. package/dist/forms.js +26 -0
  19. package/dist/index.d.ts +7 -5
  20. package/dist/index.js +10 -4
  21. package/dist/install.d.ts +16 -16
  22. package/dist/integrations/contracts.d.ts +111 -111
  23. package/dist/integrations/contracts.js +1 -1
  24. package/dist/integrations/openbanking/contracts/accounts.d.ts +73 -73
  25. package/dist/integrations/openbanking/contracts/accounts.js +1 -1
  26. package/dist/integrations/openbanking/contracts/balances.d.ts +40 -40
  27. package/dist/integrations/openbanking/contracts/balances.js +1 -1
  28. package/dist/integrations/openbanking/contracts/index.d.ts +2 -2
  29. package/dist/integrations/openbanking/contracts/transactions.d.ts +54 -54
  30. package/dist/integrations/openbanking/contracts/transactions.js +1 -1
  31. package/dist/integrations/openbanking/models.d.ts +55 -55
  32. package/dist/jsonschema.d.ts +5 -5
  33. package/dist/knowledge/contracts.d.ts +75 -75
  34. package/dist/knowledge/contracts.js +1 -1
  35. package/dist/llm/exporters.d.ts +8 -8
  36. package/dist/llm/exporters.js +1 -1
  37. package/dist/llm/prompts.d.ts +7 -7
  38. package/dist/llm/types.d.ts +3 -3
  39. package/dist/markdown.d.ts +3 -3
  40. package/dist/markdown.js +1 -1
  41. package/dist/onboarding-base.d.ts +32 -32
  42. package/dist/onboarding-base.js +1 -1
  43. package/dist/openapi.d.ts +2 -2
  44. package/dist/{spec.d.ts → operation.d.ts} +12 -12
  45. package/dist/{spec.js → operation.js} +1 -1
  46. package/dist/policy/docs/policy.docblock.js +1 -1
  47. package/dist/presentations.d.ts +14 -3
  48. package/dist/presentations.js +25 -0
  49. package/dist/registry-utils.d.ts +107 -0
  50. package/dist/registry-utils.js +122 -0
  51. package/dist/registry.d.ts +46 -14
  52. package/dist/registry.js +61 -5
  53. package/dist/server/graphql-pothos.d.ts +6 -6
  54. package/dist/server/graphql-pothos.js +4 -4
  55. package/dist/server/mcp/createMcpServer.d.ts +3 -3
  56. package/dist/server/mcp/createMcpServer.js +1 -1
  57. package/dist/server/mcp/registerTools.d.ts +2 -2
  58. package/dist/server/rest-elysia.d.ts +2 -2
  59. package/dist/server/rest-express.d.ts +2 -2
  60. package/dist/server/rest-generic.d.ts +3 -3
  61. package/dist/server/rest-generic.js +1 -1
  62. package/dist/server/rest-next-app.d.ts +4 -4
  63. package/dist/server/rest-next-app.js +2 -2
  64. package/dist/server/rest-next-mcp.d.ts +2 -2
  65. package/dist/server/rest-next-pages.d.ts +2 -2
  66. package/dist/telemetry/docs/telemetry.docblock.js +1 -1
  67. package/dist/tests/runner.d.ts +2 -2
  68. package/dist/tests/spec.d.ts +1 -1
  69. package/dist/workflow/spec.d.ts +11 -1
  70. package/dist/workflow/spec.js +26 -0
  71. package/dist/workflow/validation.d.ts +2 -2
  72. package/dist/workspace-config/contractsrc-schema.d.ts +298 -0
  73. package/dist/workspace-config/contractsrc-schema.js +139 -0
  74. package/dist/workspace-config/index.d.ts +2 -0
  75. package/dist/workspace-config/index.js +3 -0
  76. package/package.json +14 -13
  77. package/dist/presentations.backcompat.d.ts +0 -7
  78. package/dist/presentations.backcompat.js +0 -47
  79. package/dist/types/all.d.ts +0 -60
  80. package/dist/types/all.js +0 -0
@@ -1,31 +1,31 @@
1
+ import { GroupKeyFn, RegistryFilter } from "./registry-utils.js";
1
2
  import { defaultDocRegistry, docId, registerDocBlocks } from "./docs/registry.js";
2
3
  import { ResourceRefDescriptor } from "./resources.js";
3
- import { ContractSpec } from "./spec.js";
4
+ import { AnyOperationSpec, OperationSpec } from "./operation.js";
4
5
  import { HandlerCtx } from "./types.js";
5
- import { HandlerFor } from "./install.js";
6
+ import { HandlerForOperationSpec } from "./install.js";
6
7
  import { AnySchemaModel } from "@lssm/lib.schema";
7
8
 
8
9
  //#region src/registry.d.ts
9
10
 
10
11
  type OperationKey = `${string}.v${number}`;
11
12
  declare function opKey(name: string, version: number): OperationKey;
12
- type AnySpec = ContractSpec<AnySchemaModel, AnySchemaModel | ResourceRefDescriptor<boolean>>;
13
- type AnyHandler = (args: unknown, ctx: HandlerCtx) => Promise<unknown>;
13
+ type AnyOperationHandler = (args: unknown, ctx: HandlerCtx) => Promise<unknown>;
14
14
  /**
15
15
  * In-memory registry for ContractSpecs and their bound handlers.
16
16
  * Provides validation, policy enforcement, and guarded event emission at execute time.
17
17
  */
18
- declare class SpecRegistry {
18
+ declare class OperationSpecRegistry {
19
19
  private specs;
20
20
  private handlers;
21
21
  /**
22
- * Registers a ContractSpec definition.
22
+ * Registers a OperationSpec definition.
23
23
  *
24
24
  * @param spec - The contract specification to register.
25
25
  * @returns The registry instance for chaining.
26
26
  * @throws If a spec with the same name and version is already registered.
27
27
  */
28
- register<I extends AnySchemaModel, O extends AnySchemaModel | ResourceRefDescriptor<boolean>>(spec: ContractSpec<I, O>): this;
28
+ register<I extends AnySchemaModel, O extends AnySchemaModel | ResourceRefDescriptor<boolean>>(spec: OperationSpec<I, O>): this;
29
29
  /**
30
30
  * Binds a runtime handler implementation to a previously registered spec.
31
31
  *
@@ -34,7 +34,7 @@ declare class SpecRegistry {
34
34
  * @returns The registry instance for chaining.
35
35
  * @throws If the spec is not found or a handler is already bound.
36
36
  */
37
- bind<I extends AnySchemaModel, O extends AnySchemaModel | ResourceRefDescriptor<boolean>>(spec: ContractSpec<I, O>, handler: HandlerFor<ContractSpec<I, O>>): this;
37
+ bind<I extends AnySchemaModel, O extends AnySchemaModel | ResourceRefDescriptor<boolean>>(spec: OperationSpec<I, O>, handler: HandlerForOperationSpec<OperationSpec<I, O>>): this;
38
38
  /**
39
39
  * Retrieves a registered spec by name and version.
40
40
  * If version is omitted, returns the highest version found.
@@ -42,18 +42,50 @@ declare class SpecRegistry {
42
42
  * @param name - Operation name.
43
43
  * @param version - (Optional) Specific version.
44
44
  */
45
- getSpec(name: string, version?: number): AnySpec | undefined;
45
+ getSpec(name: string, version?: number): AnyOperationSpec | undefined;
46
46
  /**
47
47
  * Retrieves the bound handler for a spec.
48
48
  */
49
- getHandler(name: string, version?: number): AnyHandler | undefined;
49
+ getHandler(name: string, version?: number): AnyOperationHandler | undefined;
50
50
  /** Iterate all registered specs. */
51
- listSpecs(): AnySpec[];
51
+ listSpecs(): AnyOperationSpec[];
52
52
  /** Iterate all bound operations (spec+handler). */
53
53
  listBound(): {
54
- spec: AnySpec;
55
- handler: AnyHandler;
54
+ spec: AnyOperationSpec;
55
+ handler: AnyOperationHandler;
56
56
  }[];
57
+ /**
58
+ * Filter specs by criteria.
59
+ */
60
+ filter(criteria: RegistryFilter): AnyOperationSpec[];
61
+ /**
62
+ * List specs with specific tag.
63
+ */
64
+ listByTag(tag: string): AnyOperationSpec[];
65
+ /**
66
+ * List specs by owner.
67
+ */
68
+ listByOwner(owner: string): AnyOperationSpec[];
69
+ /**
70
+ * Group specs by key function.
71
+ */
72
+ groupBy(keyFn: GroupKeyFn<AnyOperationSpec>): Map<string, AnyOperationSpec[]>;
73
+ /**
74
+ * Group by domain (first segment of name).
75
+ */
76
+ groupByDomain(): Map<string, AnyOperationSpec[]>;
77
+ /**
78
+ * Group by tag.
79
+ */
80
+ groupByTag(): Map<string, AnyOperationSpec[]>;
81
+ /**
82
+ * Get unique tags from all specs.
83
+ */
84
+ getUniqueTags(): string[];
85
+ /**
86
+ * Get unique owners from all specs.
87
+ */
88
+ getUniqueOwners(): string[];
57
89
  /**
58
90
  * Execute an operation by name/version with full runtime protections:
59
91
  * 1. Validates input against Zod schema.
@@ -70,4 +102,4 @@ declare class SpecRegistry {
70
102
  execute(name: string, version: number | undefined, rawInput: unknown, ctx: HandlerCtx): Promise<unknown>;
71
103
  }
72
104
  //#endregion
73
- export { OperationKey, SpecRegistry, defaultDocRegistry, docId, opKey, registerDocBlocks };
105
+ export { OperationKey, OperationSpecRegistry, defaultDocRegistry, docId, opKey, registerDocBlocks };
package/dist/registry.js CHANGED
@@ -1,10 +1,12 @@
1
+ import { __toCommonJS } from "./_virtual/rolldown_runtime.js";
2
+ import { init_registry_utils, registry_utils_exports } from "./registry-utils.js";
1
3
  import { eventKey } from "./events.js";
2
- import { isEmitDeclRef } from "./spec.js";
4
+ import { isEmitDeclRef } from "./operation.js";
3
5
  import { defaultDocRegistry, docId, registerDocBlocks } from "./docs/registry.js";
4
6
 
5
7
  //#region src/registry.ts
6
8
  /**
7
- * SpecRegistry:
9
+ * OperationSpecRegistry:
8
10
  * - Registers ContractSpecs (unique by name+version)
9
11
  * - Binds runtime handlers to specs
10
12
  * - Provides lookup, iteration, and a safe execute() with validation/policy/enforcement
@@ -18,11 +20,11 @@ function opKey(name, version) {
18
20
  * In-memory registry for ContractSpecs and their bound handlers.
19
21
  * Provides validation, policy enforcement, and guarded event emission at execute time.
20
22
  */
21
- var SpecRegistry = class {
23
+ var OperationSpecRegistry = class {
22
24
  specs = /* @__PURE__ */ new Map();
23
25
  handlers = /* @__PURE__ */ new Map();
24
26
  /**
25
- * Registers a ContractSpec definition.
27
+ * Registers a OperationSpec definition.
26
28
  *
27
29
  * @param spec - The contract specification to register.
28
30
  * @returns The registry instance for chaining.
@@ -94,6 +96,60 @@ var SpecRegistry = class {
94
96
  return out;
95
97
  }
96
98
  /**
99
+ * Filter specs by criteria.
100
+ */
101
+ filter(criteria) {
102
+ const { filterBy } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
103
+ return filterBy(this.listSpecs(), criteria);
104
+ }
105
+ /**
106
+ * List specs with specific tag.
107
+ */
108
+ listByTag(tag) {
109
+ return this.listSpecs().filter((s) => s.meta.tags?.includes(tag));
110
+ }
111
+ /**
112
+ * List specs by owner.
113
+ */
114
+ listByOwner(owner) {
115
+ return this.listSpecs().filter((s) => s.meta.owners?.includes(owner));
116
+ }
117
+ /**
118
+ * Group specs by key function.
119
+ */
120
+ groupBy(keyFn) {
121
+ const { groupBy } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
122
+ return groupBy(this.listSpecs(), keyFn);
123
+ }
124
+ /**
125
+ * Group by domain (first segment of name).
126
+ */
127
+ groupByDomain() {
128
+ const { GroupingStrategies } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
129
+ return this.groupBy(GroupingStrategies.byDomain);
130
+ }
131
+ /**
132
+ * Group by tag.
133
+ */
134
+ groupByTag() {
135
+ const { GroupingStrategies } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
136
+ return this.groupBy(GroupingStrategies.byTag);
137
+ }
138
+ /**
139
+ * Get unique tags from all specs.
140
+ */
141
+ getUniqueTags() {
142
+ const { getUniqueTags } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
143
+ return getUniqueTags(this.listSpecs());
144
+ }
145
+ /**
146
+ * Get unique owners from all specs.
147
+ */
148
+ getUniqueOwners() {
149
+ const { getUniqueOwners } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
150
+ return getUniqueOwners(this.listSpecs());
151
+ }
152
+ /**
97
153
  * Execute an operation by name/version with full runtime protections:
98
154
  * 1. Validates input against Zod schema.
99
155
  * 2. Enforces policy (Auth, RBAC, Rate Limits) via PDP.
@@ -206,4 +262,4 @@ var SpecRegistry = class {
206
262
  };
207
263
 
208
264
  //#endregion
209
- export { SpecRegistry, defaultDocRegistry, docId, opKey, registerDocBlocks };
265
+ export { OperationSpecRegistry, defaultDocRegistry, docId, opKey, registerDocBlocks };
@@ -1,5 +1,5 @@
1
1
  import { ResourceRegistry } from "../resources.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
  import "@pothos/plugin-prisma";
4
4
  import "@pothos/plugin-complexity";
5
5
  import "@pothos/plugin-relay";
@@ -10,22 +10,22 @@ import { SchemaTypes } from "@pothos/core";
10
10
  //#region src/server/graphql-pothos.d.ts
11
11
 
12
12
  /**
13
- * Registers all ContractSpecs from a SpecRegistry onto a Pothos SchemaBuilder.
13
+ * Registers all ContractSpecs from a OperationSpecRegistry onto a Pothos SchemaBuilder.
14
14
  *
15
15
  * This adapter:
16
16
  * 1. Discovers output types from specs and registers them as Pothos object types.
17
- * 2. Maps `ContractSpec` inputs to Pothos input types.
17
+ * 2. Maps `ContractSpec` (OperationSpec) inputs to Pothos input types.
18
18
  * 3. Mounts `query` specs as `Query` fields and `command` specs as `Mutation` fields.
19
19
  * 4. Wraps the resolver to:
20
20
  * - Enforce auth policies (basic check).
21
21
  * - Build a `HandlerCtx`.
22
- * - Execute via `SpecRegistry`.
22
+ * - Execute via `OperationSpecRegistry`.
23
23
  * - Hydrate resource references if applicable.
24
24
  *
25
25
  * @param builder - The Pothos SchemaBuilder instance.
26
- * @param reg - The SpecRegistry containing operations.
26
+ * @param reg - The OperationSpecRegistry containing operations.
27
27
  * @param resources - (Optional) ResourceRegistry for hydrating resource references.
28
28
  */
29
- declare function registerContractsOnBuilder<T extends SchemaTypes>(builder: PothosSchemaTypes.SchemaBuilder<T>, reg: SpecRegistry, resources?: ResourceRegistry): void;
29
+ declare function registerContractsOnBuilder<T extends SchemaTypes>(builder: PothosSchemaTypes.SchemaBuilder<T>, reg: OperationSpecRegistry, resources?: ResourceRegistry): void;
30
30
  //#endregion
31
31
  export { registerContractsOnBuilder };
@@ -9,20 +9,20 @@ import "@pothos/plugin-tracing";
9
9
 
10
10
  //#region src/server/graphql-pothos.ts
11
11
  /**
12
- * Registers all ContractSpecs from a SpecRegistry onto a Pothos SchemaBuilder.
12
+ * Registers all ContractSpecs from a OperationSpecRegistry onto a Pothos SchemaBuilder.
13
13
  *
14
14
  * This adapter:
15
15
  * 1. Discovers output types from specs and registers them as Pothos object types.
16
- * 2. Maps `ContractSpec` inputs to Pothos input types.
16
+ * 2. Maps `ContractSpec` (OperationSpec) inputs to Pothos input types.
17
17
  * 3. Mounts `query` specs as `Query` fields and `command` specs as `Mutation` fields.
18
18
  * 4. Wraps the resolver to:
19
19
  * - Enforce auth policies (basic check).
20
20
  * - Build a `HandlerCtx`.
21
- * - Execute via `SpecRegistry`.
21
+ * - Execute via `OperationSpecRegistry`.
22
22
  * - Hydrate resource references if applicable.
23
23
  *
24
24
  * @param builder - The Pothos SchemaBuilder instance.
25
- * @param reg - The SpecRegistry containing operations.
25
+ * @param reg - The OperationSpecRegistry containing operations.
26
26
  * @param resources - (Optional) ResourceRegistry for hydrating resource references.
27
27
  */
28
28
  function registerContractsOnBuilder(builder, reg, resources) {
@@ -1,5 +1,5 @@
1
1
  import { ResourceRegistry } from "../../resources.js";
2
- import { SpecRegistry } from "../../registry.js";
2
+ import { OperationSpecRegistry } from "../../registry.js";
3
3
  import { PromptRegistry } from "../../promptRegistry.js";
4
4
  import { McpCtxFactories } from "./mcpTypes.js";
5
5
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -9,7 +9,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
9
9
  /**
10
10
  * Creates a unified Model Context Protocol (MCP) server exposing operations, resources, prompts,
11
11
  * and (optionally) presentations.\n+ *
12
- * ContractSpec exposes:\n+ * - Tools: `command` operations from `SpecRegistry`.\n+ * - Resources: templates from `ResourceRegistry`.\n+ * - Prompts: templates from `PromptRegistry`.\n+ * - Presentations: V1 registry and/or V2 descriptors as read-only resources.\n+ */
13
- declare function createMcpServer(server: McpServer, ops: SpecRegistry, resources: ResourceRegistry, prompts: PromptRegistry, ctxFactories: McpCtxFactories): McpServer;
12
+ * ContractSpec exposes:\n+ * - Tools: `command` operations from `OperationSpecRegistry`.\n+ * - Resources: templates from `ResourceRegistry`.\n+ * - Prompts: templates from `PromptRegistry`.\n+ * - Presentations: V1 registry and/or V2 descriptors as read-only resources.\n+ */
13
+ declare function createMcpServer(server: McpServer, ops: OperationSpecRegistry, resources: ResourceRegistry, prompts: PromptRegistry, ctxFactories: McpCtxFactories): McpServer;
14
14
  //#endregion
15
15
  export { createMcpServer };
@@ -7,7 +7,7 @@ import { registerMcpPresentations } from "./registerPresentations.js";
7
7
  /**
8
8
  * Creates a unified Model Context Protocol (MCP) server exposing operations, resources, prompts,
9
9
  * and (optionally) presentations.\n+ *
10
- * ContractSpec exposes:\n+ * - Tools: `command` operations from `SpecRegistry`.\n+ * - Resources: templates from `ResourceRegistry`.\n+ * - Prompts: templates from `PromptRegistry`.\n+ * - Presentations: V1 registry and/or V2 descriptors as read-only resources.\n+ */
10
+ * ContractSpec exposes:\n+ * - Tools: `command` operations from `OperationSpecRegistry`.\n+ * - Resources: templates from `ResourceRegistry`.\n+ * - Prompts: templates from `PromptRegistry`.\n+ * - Presentations: V1 registry and/or V2 descriptors as read-only resources.\n+ */
11
11
  function createMcpServer(server, ops, resources, prompts, ctxFactories) {
12
12
  ctxFactories.logger.info("Creating MCP server");
13
13
  registerMcpTools(server, ops, { toolCtx: ctxFactories.toolCtx });
@@ -1,8 +1,8 @@
1
- import { SpecRegistry } from "../../registry.js";
1
+ import { OperationSpecRegistry } from "../../registry.js";
2
2
  import { McpCtxFactories } from "./mcpTypes.js";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
 
5
5
  //#region src/server/mcp/registerTools.d.ts
6
- declare function registerMcpTools(server: McpServer, ops: SpecRegistry, ctx: Pick<McpCtxFactories, 'toolCtx'>): void;
6
+ declare function registerMcpTools(server: McpServer, ops: OperationSpecRegistry, ctx: Pick<McpCtxFactories, 'toolCtx'>): void;
7
7
  //#endregion
8
8
  export { registerMcpTools };
@@ -1,11 +1,11 @@
1
1
  import { HandlerCtx } from "../types.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
  import { RestOptions } from "./rest-generic.js";
4
4
  import { Elysia } from "elysia";
5
5
 
6
6
  //#region src/server/rest-elysia.d.ts
7
7
  /** Mount routes on an Elysia instance */
8
- declare function elysiaPlugin(app: Elysia, reg: SpecRegistry, ctxFactory: (c: {
8
+ declare function elysiaPlugin(app: Elysia, reg: OperationSpecRegistry, ctxFactory: (c: {
9
9
  request: Request;
10
10
  store: unknown;
11
11
  }) => HandlerCtx, options?: RestOptions): Elysia<"", {
@@ -1,5 +1,5 @@
1
1
  import { HandlerCtx } from "../types.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
  import { RestOptions } from "./rest-generic.js";
4
4
  import { Request, Router } from "express";
5
5
 
@@ -11,6 +11,6 @@ import { Request, Router } from "express";
11
11
  */
12
12
  declare function expressRouter(express: {
13
13
  Router: () => Router;
14
- }, reg: SpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): Router;
14
+ }, reg: OperationSpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): Router;
15
15
  //#endregion
16
16
  export { expressRouter };
@@ -1,5 +1,5 @@
1
1
  import { HandlerCtx } from "../types.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
 
4
4
  //#region src/server/rest-generic.d.ts
5
5
  interface RestOptions {
@@ -23,10 +23,10 @@ interface RestOptions {
23
23
  }
24
24
  /**
25
25
  * Build a single Fetch-style handler: (req) => Response
26
- * - Discovers routes from SpecRegistry
26
+ * - Discovers routes from OperationSpecRegistry
27
27
  * - Validates with zod via registry.execute()
28
28
  * - Handles CORS (optional)
29
29
  */
30
- declare function createFetchHandler(reg: SpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): (req: Request) => Promise<Response>;
30
+ declare function createFetchHandler(reg: OperationSpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): (req: Request) => Promise<Response>;
31
31
  //#endregion
32
32
  export { RestOptions, createFetchHandler };
@@ -22,7 +22,7 @@ function joinPath(a, b) {
22
22
  }
23
23
  /**
24
24
  * Build a single Fetch-style handler: (req) => Response
25
- * - Discovers routes from SpecRegistry
25
+ * - Discovers routes from OperationSpecRegistry
26
26
  * - Validates with zod via registry.execute()
27
27
  * - Handles CORS (optional)
28
28
  */
@@ -1,5 +1,5 @@
1
1
  import { HandlerCtx } from "../types.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
  import { RestOptions } from "./rest-generic.js";
4
4
 
5
5
  //#region src/server/rest-next-app.d.ts
@@ -12,10 +12,10 @@ import { RestOptions } from "./rest-generic.js";
12
12
  * - Path parsing to determine the operation name and version.
13
13
  * - Body parsing (JSON).
14
14
  * - Context creation via `ctxFactory`.
15
- * - Execution via `SpecRegistry`.
15
+ * - Execution via `OperationSpecRegistry`.
16
16
  * - Response formatting (JSON success/error).
17
17
  *
18
- * @param reg - The SpecRegistry containing the operations.
18
+ * @param reg - The OperationSpecRegistry containing the operations.
19
19
  * @param ctxFactory - A factory function to build the `HandlerCtx` (e.g., auth, tenant) from the request.
20
20
  * @param options - Optional configuration for the REST handler.
21
21
  * @returns A function `(req: Request) => Promise<Response>`.
@@ -30,6 +30,6 @@ import { RestOptions } from "./rest-generic.js";
30
30
  * export { handler as GET, handler as POST };
31
31
  * ```
32
32
  */
33
- declare function makeNextAppHandler(reg: SpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): (req: Request) => Promise<Response>;
33
+ declare function makeNextAppHandler(reg: OperationSpecRegistry, ctxFactory: (req: Request) => HandlerCtx, options?: RestOptions): (req: Request) => Promise<Response>;
34
34
  //#endregion
35
35
  export { makeNextAppHandler };
@@ -9,10 +9,10 @@ import { createFetchHandler } from "./rest-generic.js";
9
9
  * - Path parsing to determine the operation name and version.
10
10
  * - Body parsing (JSON).
11
11
  * - Context creation via `ctxFactory`.
12
- * - Execution via `SpecRegistry`.
12
+ * - Execution via `OperationSpecRegistry`.
13
13
  * - Response formatting (JSON success/error).
14
14
  *
15
- * @param reg - The SpecRegistry containing the operations.
15
+ * @param reg - The OperationSpecRegistry containing the operations.
16
16
  * @param ctxFactory - A factory function to build the `HandlerCtx` (e.g., auth, tenant) from the request.
17
17
  * @param options - Optional configuration for the REST handler.
18
18
  * @returns A function `(req: Request) => Promise<Response>`.
@@ -1,8 +1,8 @@
1
1
  import { HandlerCtx } from "../types.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
 
4
4
  //#region src/server/rest-next-mcp.d.ts
5
- declare function makeNextMcpServerFromRegistry(reg: SpecRegistry, ctxFactory: () => HandlerCtx): {
5
+ declare function makeNextMcpServerFromRegistry(reg: OperationSpecRegistry, ctxFactory: () => HandlerCtx): {
6
6
  GET: (request: Request) => Promise<Response>;
7
7
  POST: (request: Request) => Promise<Response>;
8
8
  DELETE: (request: Request) => Promise<Response>;
@@ -1,9 +1,9 @@
1
1
  import { HandlerCtx } from "../types.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
  import { RestOptions } from "./rest-generic.js";
4
4
  import { NextApiRequest, NextApiResponse } from "next";
5
5
 
6
6
  //#region src/server/rest-next-pages.d.ts
7
- declare function makeNextPagesHandler(reg: SpecRegistry, ctxFactory: (req: NextApiRequest) => HandlerCtx, options?: RestOptions): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
7
+ declare function makeNextPagesHandler(reg: OperationSpecRegistry, ctxFactory: (req: NextApiRequest) => HandlerCtx, options?: RestOptions): (req: NextApiRequest, res: NextApiResponse) => Promise<void>;
8
8
  //#endregion
9
9
  export { makeNextPagesHandler };
@@ -14,7 +14,7 @@ const tech_contracts_telemetry_DocBlocks = [{
14
14
  "contracts",
15
15
  "telemetry"
16
16
  ],
17
- body: "## TelemetrySpec\n\nTelemetry specs describe product analytics in a durable, type-safe way. They reference existing `EventSpec`s (same name/version) but layer on privacy classification, retention, sampling, and anomaly detection so instrumentation stays compliant and observable.\n\n- **File location**: `packages/libs/contracts/src/telemetry/spec.ts`\n- **Runtime tracker**: `packages/libs/contracts/src/telemetry/tracker.ts`\n- **Anomaly monitor**: `packages/libs/contracts/src/telemetry/anomaly.ts`\n\n### Core concepts\n\n```ts\nexport interface TelemetrySpec {\n meta: TelemetryMeta;\n events: TelemetryEventDef[];\n config?: TelemetryConfig;\n}\n```\n\n- `meta`: ownership + identifiers (`name`, `version`, `domain`)\n- `events`: per-event semantics, property definitions, privacy level, retention, sampling, anomaly rules\n- `config`: defaults and provider configuration\n- `TelemetryRegistry`: registers specs, resolves latest version, finds event definitions by name/version\n\n### An example\n\n```ts\nexport const SigilTelemetry: TelemetrySpec = {\n meta: {\n name: 'sigil.telemetry',\n version: 1,\n title: 'Sigil telemetry',\n description: 'Core Sigil product telemetry',\n domain: 'sigil',\n owners: ['@team.analytics'],\n tags: ['telemetry'],\n stability: StabilityEnum.Experimental,\n },\n config: {\n defaultRetentionDays: 30,\n defaultSamplingRate: 1,\n providers: [\n { type: 'posthog', config: { projectApiKey: process.env.POSTHOG_KEY } },\n ],\n },\n events: [\n {\n name: 'sigil.telemetry.workflow_step',\n version: 1,\n semantics: {\n what: 'Workflow step executed',\n who: 'Actor executing the workflow',\n },\n privacy: 'internal',\n properties: {\n workflow: { type: 'string', required: true },\n step: { type: 'string', required: true },\n durationMs: { type: 'number' },\n userId: { type: 'string', pii: true, redact: true },\n },\n anomalyDetection: {\n enabled: true,\n minimumSample: 10,\n thresholds: [\n { metric: 'durationMs', max: 1500 },\n ],\n actions: ['alert', 'trigger_regen'],\n },\n },\n ],\n};\n```\n\n### Tracking events at runtime\n\n`TelemetryTracker` performs sampling, PII redaction, provider dispatch, and anomaly detection.\n\n```ts\nconst tracker = new TelemetryTracker({\n registry: telemetryRegistry,\n providers: [\n {\n id: 'posthog',\n async send(dispatch) {\n posthog.capture({\n event: dispatch.name,\n properties: dispatch.properties,\n distinctId: dispatch.context.userId ?? dispatch.context.sessionId,\n });\n },\n },\n ],\n anomalyMonitor: new TelemetryAnomalyMonitor({\n onAnomaly(event) {\n console.warn('Telemetry anomaly detected', event);\n },\n }),\n});\n\nawait tracker.track('sigil.telemetry.workflow_step', 1, {\n workflow: 'onboarding',\n step: 'verify_email',\n durationMs: 2100,\n userId: 'user-123',\n});\n```\n\n- Sampling obeys the event-specific rate (fallback to spec defaults)\n- Properties flagged with `pii` or `redact` are masked before dispatch\n- Anomaly monitor evaluates thresholds and triggers actions (e.g., log, alert, regeneration)\n\n### Spec integration\n\n- `ContractSpec.telemetry` allows operations to emit success/failure events automatically\n- `SpecRegistry.execute()` uses the tracker when `ctx.telemetry` is provided\n- `WorkflowRunner` (Phase 4 follow-up) will emit telemetry during step transitions\n- `TelemetrySpec` events should reuse `EventSpec` names/versions to keep analytics/contract parity\n\n### CLI workflow\n\n```\ncontracts-cli create telemetry\n```\n\n- Interactive wizard prompts for meta, providers, events, properties, retention, anomaly rules\n- Output: `*.telemetry.ts` file using `TelemetrySpec`\n\n### Best practices\n\n- Prefer `internal` privacy for non-PII; mark PII properties explicitly with `pii` + `redact`\n- Keep sampling ≥0.05 except for high-volume events\n- Configure anomaly detection on key metrics (duration, error count, conversion)\n- Check telemetry into source control alongside contracts; regenerate via CLI when specs change\n\n### Next steps\n\n- Phase 5: Regenerator monitors telemetry anomalies to propose spec improvements\n- Phase 6: Studio surfaces telemetry controls per tenant via `TenantAppConfig`\n\n"
17
+ body: "## TelemetrySpec\n\nTelemetry specs describe product analytics in a durable, type-safe way. They reference existing `EventSpec`s (same name/version) but layer on privacy classification, retention, sampling, and anomaly detection so instrumentation stays compliant and observable.\n\n- **File location**: `packages/libs/contracts/src/telemetry/spec.ts`\n- **Runtime tracker**: `packages/libs/contracts/src/telemetry/tracker.ts`\n- **Anomaly monitor**: `packages/libs/contracts/src/telemetry/anomaly.ts`\n\n### Core concepts\n\n```ts\nexport interface TelemetrySpec {\n meta: TelemetryMeta;\n events: TelemetryEventDef[];\n config?: TelemetryConfig;\n}\n```\n\n- `meta`: ownership + identifiers (`name`, `version`, `domain`)\n- `events`: per-event semantics, property definitions, privacy level, retention, sampling, anomaly rules\n- `config`: defaults and provider configuration\n- `TelemetryRegistry`: registers specs, resolves latest version, finds event definitions by name/version\n\n### An example\n\n```ts\nexport const SigilTelemetry: TelemetrySpec = {\n meta: {\n name: 'sigil.telemetry',\n version: 1,\n title: 'Sigil telemetry',\n description: 'Core Sigil product telemetry',\n domain: 'sigil',\n owners: ['@team.analytics'],\n tags: ['telemetry'],\n stability: StabilityEnum.Experimental,\n },\n config: {\n defaultRetentionDays: 30,\n defaultSamplingRate: 1,\n providers: [\n { type: 'posthog', config: { projectApiKey: process.env.POSTHOG_KEY } },\n ],\n },\n events: [\n {\n name: 'sigil.telemetry.workflow_step',\n version: 1,\n semantics: {\n what: 'Workflow step executed',\n who: 'Actor executing the workflow',\n },\n privacy: 'internal',\n properties: {\n workflow: { type: 'string', required: true },\n step: { type: 'string', required: true },\n durationMs: { type: 'number' },\n userId: { type: 'string', pii: true, redact: true },\n },\n anomalyDetection: {\n enabled: true,\n minimumSample: 10,\n thresholds: [\n { metric: 'durationMs', max: 1500 },\n ],\n actions: ['alert', 'trigger_regen'],\n },\n },\n ],\n};\n```\n\n### Tracking events at runtime\n\n`TelemetryTracker` performs sampling, PII redaction, provider dispatch, and anomaly detection.\n\n```ts\nconst tracker = new TelemetryTracker({\n registry: telemetryRegistry,\n providers: [\n {\n id: 'posthog',\n async send(dispatch) {\n posthog.capture({\n event: dispatch.name,\n properties: dispatch.properties,\n distinctId: dispatch.context.userId ?? dispatch.context.sessionId,\n });\n },\n },\n ],\n anomalyMonitor: new TelemetryAnomalyMonitor({\n onAnomaly(event) {\n console.warn('Telemetry anomaly detected', event);\n },\n }),\n});\n\nawait tracker.track('sigil.telemetry.workflow_step', 1, {\n workflow: 'onboarding',\n step: 'verify_email',\n durationMs: 2100,\n userId: 'user-123',\n});\n```\n\n- Sampling obeys the event-specific rate (fallback to spec defaults)\n- Properties flagged with `pii` or `redact` are masked before dispatch\n- Anomaly monitor evaluates thresholds and triggers actions (e.g., log, alert, regeneration)\n\n### Spec integration\n\n- `ContractSpec.telemetry` allows operations to emit success/failure events automatically\n- `OperationSpecRegistry.execute()` uses the tracker when `ctx.telemetry` is provided\n- `WorkflowRunner` (Phase 4 follow-up) will emit telemetry during step transitions\n- `TelemetrySpec` events should reuse `EventSpec` names/versions to keep analytics/contract parity\n\n### CLI workflow\n\n```\ncontracts-cli create telemetry\n```\n\n- Interactive wizard prompts for meta, providers, events, properties, retention, anomaly rules\n- Output: `*.telemetry.ts` file using `TelemetrySpec`\n\n### Best practices\n\n- Prefer `internal` privacy for non-PII; mark PII properties explicitly with `pii` + `redact`\n- Keep sampling ≥0.05 except for high-volume events\n- Configure anomaly detection on key metrics (duration, error count, conversion)\n- Check telemetry into source control alongside contracts; regenerate via CLI when specs change\n\n### Next steps\n\n- Phase 5: Regenerator monitors telemetry anomalies to propose spec improvements\n- Phase 6: Studio surfaces telemetry controls per tenant via `TenantAppConfig`\n\n"
18
18
  }];
19
19
  registerDocBlocks(tech_contracts_telemetry_DocBlocks);
20
20
 
@@ -1,6 +1,6 @@
1
1
  import { Assertion, TestScenario, TestSpec } from "./spec.js";
2
2
  import { HandlerCtx } from "../types.js";
3
- import { SpecRegistry } from "../registry.js";
3
+ import { OperationSpecRegistry } from "../registry.js";
4
4
  import "../index.js";
5
5
 
6
6
  //#region src/tests/runner.d.ts
@@ -22,7 +22,7 @@ interface TestRunResult {
22
22
  failed: number;
23
23
  }
24
24
  interface TestRunnerConfig {
25
- registry: SpecRegistry;
25
+ registry: OperationSpecRegistry;
26
26
  createContext?: () => HandlerCtx | Promise<HandlerCtx>;
27
27
  beforeEach?: (scenario: TestScenario) => void | Promise<void>;
28
28
  afterEach?: (scenario: TestScenario, result: ScenarioRunResult) => void | Promise<void>;
@@ -10,7 +10,7 @@ interface WorkflowTargetRef {
10
10
  version?: number;
11
11
  }
12
12
  type TestTarget = {
13
- type: 'contract';
13
+ type: 'operation';
14
14
  operation: OperationTargetRef;
15
15
  } | {
16
16
  type: 'workflow';
@@ -1,10 +1,10 @@
1
1
  import { OwnerShipMeta } from "../ownership.js";
2
+ import { GroupKeyFn, RegistryFilter } from "../registry-utils.js";
2
3
  import { CapabilityRef } from "../capabilities.js";
3
4
  import { ExperimentRef } from "../experiments/spec.js";
4
5
  import { OpRef } from "../features.js";
5
6
 
6
7
  //#region src/workflow/spec.d.ts
7
-
8
8
  /**
9
9
  * Reference to a form spec declared in {@link FormRegistry}.
10
10
  */
@@ -94,6 +94,16 @@ declare class WorkflowRegistry {
94
94
  register(spec: WorkflowSpec): this;
95
95
  list(): WorkflowSpec[];
96
96
  get(name: string, version?: number): WorkflowSpec | undefined;
97
+ /** Filter workflows by criteria. */
98
+ filter(criteria: RegistryFilter): WorkflowSpec[];
99
+ /** List workflows with specific tag. */
100
+ listByTag(tag: string): WorkflowSpec[];
101
+ /** List workflows by owner. */
102
+ listByOwner(owner: string): WorkflowSpec[];
103
+ /** Group workflows by key function. */
104
+ groupBy(keyFn: GroupKeyFn<WorkflowSpec>): Map<string, WorkflowSpec[]>;
105
+ /** Get unique tags from all workflows. */
106
+ getUniqueTags(): string[];
97
107
  }
98
108
  //#endregion
99
109
  export { CompensationStep, CompensationStrategy, FormRef, GuardCondition, GuardConditionKind, RetryPolicy, SLA, Step, StepAction, StepType, Transition, WorkflowDefinition, WorkflowMeta, WorkflowRegistry, WorkflowSpec, WorkflowStatus };
@@ -1,3 +1,6 @@
1
+ import { __toCommonJS } from "../_virtual/rolldown_runtime.js";
2
+ import { init_registry_utils, registry_utils_exports } from "../registry-utils.js";
3
+
1
4
  //#region src/workflow/spec.ts
2
5
  function workflowKey(meta) {
3
6
  return `${meta.name}.v${meta.version}`;
@@ -26,6 +29,29 @@ var WorkflowRegistry = class {
26
29
  }
27
30
  return candidate;
28
31
  }
32
+ /** Filter workflows by criteria. */
33
+ filter(criteria) {
34
+ const { filterBy } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
35
+ return filterBy(this.list(), criteria);
36
+ }
37
+ /** List workflows with specific tag. */
38
+ listByTag(tag) {
39
+ return this.list().filter((w) => w.meta.tags?.includes(tag));
40
+ }
41
+ /** List workflows by owner. */
42
+ listByOwner(owner) {
43
+ return this.list().filter((w) => w.meta.owners?.includes(owner));
44
+ }
45
+ /** Group workflows by key function. */
46
+ groupBy(keyFn) {
47
+ const { groupBy } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
48
+ return groupBy(this.list(), keyFn);
49
+ }
50
+ /** Get unique tags from all workflows. */
51
+ getUniqueTags() {
52
+ const { getUniqueTags } = (init_registry_utils(), __toCommonJS(registry_utils_exports));
53
+ return getUniqueTags(this.list());
54
+ }
29
55
  };
30
56
 
31
57
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { WorkflowSpec } from "./spec.js";
2
- import { SpecRegistry } from "../registry.js";
2
+ import { OperationSpecRegistry } from "../registry.js";
3
3
  import { FormRegistry } from "../forms.js";
4
4
 
5
5
  //#region src/workflow/validation.d.ts
@@ -10,7 +10,7 @@ interface WorkflowValidationIssue {
10
10
  context?: Record<string, unknown>;
11
11
  }
12
12
  interface ValidateWorkflowSpecOptions {
13
- operations?: SpecRegistry;
13
+ operations?: OperationSpecRegistry;
14
14
  forms?: FormRegistry;
15
15
  }
16
16
  declare class WorkflowValidationError extends Error {