@contractspec/lib.contracts 0.0.0-canary-20260119225944 → 0.0.0-canary-20260202053150

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 (166) hide show
  1. package/dist/app-config/{contracts.d.ts → app-config.contracts.d.ts} +52 -52
  2. package/dist/app-config/{contracts.js → app-config.contracts.js} +1 -1
  3. package/dist/app-config/lifecycle-contracts.d.ts +55 -55
  4. package/dist/app-config/runtime.d.ts +4 -4
  5. package/dist/app-config/spec.d.ts +2 -2
  6. package/dist/capabilities/capabilities.d.ts +64 -5
  7. package/dist/capabilities/capabilities.js +125 -0
  8. package/dist/capabilities/context.d.ts +88 -0
  9. package/dist/capabilities/context.js +87 -0
  10. package/dist/capabilities/docs/capabilities.docblock.js +191 -2
  11. package/dist/capabilities/guards.d.ts +110 -0
  12. package/dist/capabilities/guards.js +146 -0
  13. package/dist/capabilities/index.d.ts +4 -1
  14. package/dist/capabilities/index.js +4 -1
  15. package/dist/capabilities/validation.d.ts +76 -0
  16. package/dist/capabilities/validation.js +141 -0
  17. package/dist/client/react/feature-render.d.ts +2 -2
  18. package/dist/data-views/data-views.d.ts +2 -1
  19. package/dist/data-views/index.d.ts +2 -1
  20. package/dist/data-views/registry.d.ts +1 -1
  21. package/dist/data-views/report/contractVerificationTable.d.ts +10 -0
  22. package/dist/data-views/report/contractVerificationTable.js +95 -0
  23. package/dist/data-views/runtime.d.ts +2 -2
  24. package/dist/data-views/spec.d.ts +2 -8
  25. package/dist/data-views/types.d.ts +1 -1
  26. package/dist/docs/capabilities/documentationSystem.capability.d.ts +7 -0
  27. package/dist/docs/capabilities/documentationSystem.capability.js +71 -0
  28. package/dist/docs/capabilities/index.d.ts +2 -0
  29. package/dist/docs/capabilities/index.js +3 -0
  30. package/dist/docs/commands/docsGenerate.command.d.ts +95 -0
  31. package/dist/docs/commands/docsGenerate.command.js +142 -0
  32. package/dist/docs/commands/docsPublish.command.d.ts +64 -0
  33. package/dist/docs/commands/docsPublish.command.js +107 -0
  34. package/dist/docs/commands/index.d.ts +3 -0
  35. package/dist/docs/commands/index.js +4 -0
  36. package/dist/docs/constants.d.ts +7 -0
  37. package/dist/docs/constants.js +10 -0
  38. package/dist/docs/contracts.d.ts +442 -0
  39. package/dist/docs/contracts.js +58 -0
  40. package/dist/docs/ensure-docblocks.d.ts +1 -0
  41. package/dist/docs/ensure-docblocks.js +1 -0
  42. package/dist/docs/events/docsGenerated.event.d.ts +62 -0
  43. package/dist/docs/events/docsGenerated.event.js +53 -0
  44. package/dist/docs/events/docsPublished.event.d.ts +70 -0
  45. package/dist/docs/events/docsPublished.event.js +57 -0
  46. package/dist/docs/events/index.d.ts +3 -0
  47. package/dist/docs/events/index.js +4 -0
  48. package/dist/docs/forms/docsSearch.form.d.ts +22 -0
  49. package/dist/docs/forms/docsSearch.form.js +113 -0
  50. package/dist/docs/forms/index.d.ts +2 -0
  51. package/dist/docs/forms/index.js +3 -0
  52. package/dist/docs/index.d.ts +23 -2
  53. package/dist/docs/index.js +25 -1
  54. package/dist/docs/presentations/docsLayout.presentation.d.ts +7 -0
  55. package/dist/docs/presentations/docsLayout.presentation.js +35 -0
  56. package/dist/docs/presentations/docsReferencePage.presentation.d.ts +7 -0
  57. package/dist/docs/presentations/docsReferencePage.presentation.js +35 -0
  58. package/dist/docs/presentations/index.d.ts +3 -0
  59. package/dist/docs/presentations/index.js +4 -0
  60. package/dist/docs/queries/contractReference.query.d.ts +217 -0
  61. package/dist/docs/queries/contractReference.query.js +125 -0
  62. package/dist/docs/queries/docsIndex.query.d.ts +272 -0
  63. package/dist/docs/queries/docsIndex.query.js +133 -0
  64. package/dist/docs/queries/index.d.ts +3 -0
  65. package/dist/docs/queries/index.js +4 -0
  66. package/dist/docs/tech/cli.docblock.js +10 -0
  67. package/dist/docs/tech/docs-system.docblock.d.ts +1 -0
  68. package/dist/docs/tech/docs-system.docblock.js +128 -0
  69. package/dist/docs/tech/report-verification-table.docblock.d.ts +1 -0
  70. package/dist/docs/tech/report-verification-table.docblock.js +50 -0
  71. package/dist/docs/views/contractReference.dataView.d.ts +7 -0
  72. package/dist/docs/views/contractReference.dataView.js +80 -0
  73. package/dist/docs/views/docsIndex.dataView.d.ts +7 -0
  74. package/dist/docs/views/docsIndex.dataView.js +136 -0
  75. package/dist/docs/views/exampleCatalog.dataView.d.ts +7 -0
  76. package/dist/docs/views/exampleCatalog.dataView.js +91 -0
  77. package/dist/docs/views/index.d.ts +4 -0
  78. package/dist/docs/views/index.js +5 -0
  79. package/dist/events.d.ts +80 -14
  80. package/dist/events.js +33 -3
  81. package/dist/examples/schema.d.ts +12 -12
  82. package/dist/examples/types.d.ts +1 -1
  83. package/dist/experiments/spec.d.ts +9 -6
  84. package/dist/features/index.d.ts +2 -2
  85. package/dist/features/install.d.ts +4 -4
  86. package/dist/features/types.d.ts +28 -32
  87. package/dist/forms/forms.d.ts +1 -1
  88. package/dist/index.d.ts +60 -31
  89. package/dist/index.js +32 -4
  90. package/dist/install.d.ts +1 -1
  91. package/dist/integrations/openbanking/contracts/accounts.d.ts +67 -67
  92. package/dist/integrations/openbanking/contracts/balances.d.ts +35 -35
  93. package/dist/integrations/openbanking/contracts/transactions.d.ts +49 -49
  94. package/dist/integrations/openbanking/models.d.ts +55 -55
  95. package/dist/integrations/operations.d.ts +103 -103
  96. package/dist/integrations/spec.d.ts +2 -2
  97. package/dist/jsonschema.d.ts +1 -1
  98. package/dist/knowledge/operations.d.ts +67 -67
  99. package/dist/knowledge/spec.d.ts +1 -1
  100. package/dist/llm/exporters.d.ts +4 -4
  101. package/dist/llm/types.d.ts +1 -1
  102. package/dist/markdown.d.ts +2 -2
  103. package/dist/operations/index.d.ts +4 -1
  104. package/dist/operations/index.js +4 -1
  105. package/dist/operations/operation.d.ts +8 -2
  106. package/dist/operations/registry.d.ts +1 -1
  107. package/dist/operations/report/getContractVerificationStatus.d.ts +75 -0
  108. package/dist/operations/report/getContractVerificationStatus.js +96 -0
  109. package/dist/operations/report/index.d.ts +13 -0
  110. package/dist/operations/report/index.js +45 -0
  111. package/dist/ownership.d.ts +133 -8
  112. package/dist/ownership.js +25 -0
  113. package/dist/policy/context.d.ts +237 -0
  114. package/dist/policy/context.js +227 -0
  115. package/dist/policy/guards.d.ts +145 -0
  116. package/dist/policy/guards.js +254 -0
  117. package/dist/policy/index.d.ts +12 -1
  118. package/dist/policy/index.js +11 -1
  119. package/dist/policy/spec.d.ts +7 -4
  120. package/dist/policy/validation.d.ts +67 -0
  121. package/dist/policy/validation.js +307 -0
  122. package/dist/presentations/presentations.d.ts +6 -0
  123. package/dist/presentations/registry.d.ts +1 -1
  124. package/dist/registry.d.ts +1 -1
  125. package/dist/serialization/index.d.ts +3 -0
  126. package/dist/serialization/index.js +3 -0
  127. package/dist/serialization/serializers.d.ts +40 -0
  128. package/dist/serialization/serializers.js +148 -0
  129. package/dist/serialization/types.d.ts +103 -0
  130. package/dist/serialization/types.js +0 -0
  131. package/dist/server/rest-elysia.d.ts +1 -1
  132. package/dist/server/rest-express.d.ts +1 -1
  133. package/dist/server/rest-generic.d.ts +1 -1
  134. package/dist/server/rest-next-app.d.ts +1 -1
  135. package/dist/server/rest-next-mcp.d.ts +1 -1
  136. package/dist/server/rest-next-pages.d.ts +1 -1
  137. package/dist/telemetry/spec.d.ts +1 -1
  138. package/dist/telemetry/tracker.d.ts +3 -2
  139. package/dist/tests/runner.d.ts +1 -1
  140. package/dist/tests/spec.d.ts +17 -12
  141. package/dist/themes.d.ts +8 -5
  142. package/dist/translations/index.d.ts +6 -0
  143. package/dist/translations/index.js +5 -0
  144. package/dist/translations/registry.d.ts +144 -0
  145. package/dist/translations/registry.js +223 -0
  146. package/dist/translations/spec.d.ts +126 -0
  147. package/dist/translations/spec.js +31 -0
  148. package/dist/translations/validation.d.ts +85 -0
  149. package/dist/translations/validation.js +328 -0
  150. package/dist/types.d.ts +142 -16
  151. package/dist/versioning/index.d.ts +2 -1
  152. package/dist/versioning/index.js +2 -1
  153. package/dist/versioning/refs.d.ts +179 -0
  154. package/dist/versioning/refs.js +161 -0
  155. package/dist/workflow/context.d.ts +191 -0
  156. package/dist/workflow/context.js +227 -0
  157. package/dist/workflow/index.d.ts +6 -3
  158. package/dist/workflow/index.js +4 -2
  159. package/dist/workflow/spec.d.ts +4 -11
  160. package/dist/workflow/validation.d.ts +64 -2
  161. package/dist/workflow/validation.js +194 -1
  162. package/dist/workspace-config/contractsrc-schema.d.ts +3 -3
  163. package/dist/workspace-config/contractsrc-schema.js +1 -0
  164. package/dist/workspace-config/contractsrc-types.d.ts +7 -8
  165. package/dist/workspace-config/index.d.ts +2 -2
  166. package/package.json +52 -9
@@ -1,39 +1,98 @@
1
+ import { VersionedSpecRef } from "../versioning/refs.js";
1
2
  import { OwnerShipMeta } from "../ownership.js";
2
3
 
3
4
  //#region src/capabilities/capabilities.d.ts
5
+ /** Classification of capability types. */
4
6
  type CapabilityKind = 'api' | 'event' | 'data' | 'ui' | 'integration';
7
+ /** Surfaces where capabilities can be exposed or consumed. */
5
8
  type CapabilitySurface = 'operation' | 'event' | 'workflow' | 'presentation' | 'resource';
9
+ /**
10
+ * Reference to a capability on a specific surface.
11
+ * Extends VersionedSpecRef with surface and description context.
12
+ */
6
13
  interface CapabilitySurfaceRef {
14
+ /** The surface type where this capability is exposed. */
7
15
  surface: CapabilitySurface;
16
+ /** Unique key identifying the spec on that surface (e.g., operation key). */
8
17
  key: string;
9
- version: string;
18
+ /** Semantic version of the spec on that surface. */
19
+ version?: string;
20
+ /** Optional description of what this capability provides. */
10
21
  description?: string;
11
22
  }
23
+ /** Metadata for a capability spec, extending ownership with kind. */
12
24
  interface CapabilityMeta extends OwnerShipMeta {
25
+ /** The kind/category of this capability. */
13
26
  kind: CapabilityKind;
14
27
  }
28
+ /**
29
+ * Requirement for a capability dependency.
30
+ * Used to declare what capabilities a spec needs.
31
+ */
15
32
  interface CapabilityRequirement {
33
+ /** Unique key of the required capability. */
16
34
  key: string;
35
+ /** Optional specific version required. */
17
36
  version?: string;
37
+ /** Optional kind filter for the requirement. */
18
38
  kind?: CapabilityKind;
39
+ /** If true, the requirement is optional and won't block if missing. */
19
40
  optional?: boolean;
41
+ /** Human-readable reason why this capability is required. */
20
42
  reason?: string;
21
43
  }
22
- interface CapabilityRef {
23
- key: string;
24
- version: string;
25
- }
44
+ /**
45
+ * Reference to a capability spec.
46
+ * Uses key and version to identify a specific capability.
47
+ */
48
+ type CapabilityRef = VersionedSpecRef;
26
49
  interface CapabilitySpec {
27
50
  meta: CapabilityMeta;
51
+ /** Capabilities this capability extends (inherits requirements from). */
52
+ extends?: CapabilityRef;
53
+ /** Surfaces (operations, events, presentations, etc.) this capability provides. */
28
54
  provides?: CapabilitySurfaceRef[];
55
+ /** Capabilities that must be present for this capability to function. */
29
56
  requires?: CapabilityRequirement[];
30
57
  }
31
58
  declare class CapabilityRegistry {
32
59
  private readonly items;
60
+ /** Reverse index: surface key -> capability key (built lazily) */
61
+ private surfaceIndex;
33
62
  register(spec: CapabilitySpec): this;
34
63
  list(): CapabilitySpec[];
35
64
  get(key: string, version?: string): CapabilitySpec | undefined;
36
65
  satisfies(requirement: CapabilityRequirement, additional?: CapabilityRef[] | undefined): boolean;
66
+ /** Build reverse index from surface specs to capabilities. */
67
+ private buildSurfaceIndex;
68
+ /** Get all operation keys provided by a capability. */
69
+ getOperationsFor(capabilityKey: string, version?: string): string[];
70
+ /** Get all event keys provided by a capability. */
71
+ getEventsFor(capabilityKey: string, version?: string): string[];
72
+ /** Get all presentation keys provided by a capability. */
73
+ getPresentationsFor(capabilityKey: string, version?: string): string[];
74
+ /** Get all workflow keys provided by a capability. */
75
+ getWorkflowsFor(capabilityKey: string, version?: string): string[];
76
+ /** Get all resource keys provided by a capability. */
77
+ getResourcesFor(capabilityKey: string, version?: string): string[];
78
+ /** Get capability refs that provide a specific operation. */
79
+ getCapabilitiesForOperation(operationKey: string): CapabilityRef[];
80
+ /** Get capability refs that provide a specific event. */
81
+ getCapabilitiesForEvent(eventKey: string): CapabilityRef[];
82
+ /** Get capability refs that provide a specific presentation. */
83
+ getCapabilitiesForPresentation(presentationKey: string): CapabilityRef[];
84
+ /** Get the ancestor chain for a capability (from immediate parent to root). */
85
+ getAncestors(capabilityKey: string, version?: string): CapabilitySpec[];
86
+ /**
87
+ * Get effective requirements for a capability, including inherited ones.
88
+ * Requirements from ancestors are included, with child requirements taking
89
+ * precedence over parent requirements for the same key.
90
+ */
91
+ getEffectiveRequirements(capabilityKey: string, version?: string): CapabilityRequirement[];
92
+ /**
93
+ * Get all surfaces provided by a capability, including inherited ones.
94
+ */
95
+ getEffectiveSurfaces(capabilityKey: string, version?: string): CapabilitySurfaceRef[];
37
96
  }
38
97
  declare function capabilityKey(spec: CapabilitySpec): string;
39
98
  declare function defineCapability(spec: CapabilitySpec): CapabilitySpec;
@@ -4,10 +4,13 @@ import { compareVersions } from "compare-versions";
4
4
  const capKey = (key, version) => `${key}.v${version}`;
5
5
  var CapabilityRegistry = class {
6
6
  items = /* @__PURE__ */ new Map();
7
+ /** Reverse index: surface key -> capability key (built lazily) */
8
+ surfaceIndex = null;
7
9
  register(spec) {
8
10
  const key = capKey(spec.meta.key, spec.meta.version);
9
11
  if (this.items.has(key)) throw new Error(`Duplicate capability ${key}`);
10
12
  this.items.set(key, spec);
13
+ this.surfaceIndex = null;
11
14
  return this;
12
15
  }
13
16
  list() {
@@ -31,6 +34,128 @@ var CapabilityRegistry = class {
31
34
  if (requirement.version != null && spec.meta.version !== requirement.version) return false;
32
35
  return true;
33
36
  }
37
+ /** Build reverse index from surface specs to capabilities. */
38
+ buildSurfaceIndex() {
39
+ if (this.surfaceIndex) return this.surfaceIndex;
40
+ this.surfaceIndex = /* @__PURE__ */ new Map();
41
+ for (const spec of this.items.values()) {
42
+ const capabilityKey$1 = capKey(spec.meta.key, spec.meta.version);
43
+ for (const surface of spec.provides ?? []) {
44
+ const surfaceKey = `${surface.surface}:${surface.key}`;
45
+ if (!this.surfaceIndex.has(surfaceKey)) this.surfaceIndex.set(surfaceKey, /* @__PURE__ */ new Set());
46
+ this.surfaceIndex.get(surfaceKey)?.add(capabilityKey$1);
47
+ }
48
+ }
49
+ return this.surfaceIndex;
50
+ }
51
+ /** Get all operation keys provided by a capability. */
52
+ getOperationsFor(capabilityKey$1, version) {
53
+ const spec = this.get(capabilityKey$1, version);
54
+ if (!spec) return [];
55
+ return spec.provides?.filter((s) => s.surface === "operation").map((s) => s.key) ?? [];
56
+ }
57
+ /** Get all event keys provided by a capability. */
58
+ getEventsFor(capabilityKey$1, version) {
59
+ const spec = this.get(capabilityKey$1, version);
60
+ if (!spec) return [];
61
+ return spec.provides?.filter((s) => s.surface === "event").map((s) => s.key) ?? [];
62
+ }
63
+ /** Get all presentation keys provided by a capability. */
64
+ getPresentationsFor(capabilityKey$1, version) {
65
+ const spec = this.get(capabilityKey$1, version);
66
+ if (!spec) return [];
67
+ return spec.provides?.filter((s) => s.surface === "presentation").map((s) => s.key) ?? [];
68
+ }
69
+ /** Get all workflow keys provided by a capability. */
70
+ getWorkflowsFor(capabilityKey$1, version) {
71
+ const spec = this.get(capabilityKey$1, version);
72
+ if (!spec) return [];
73
+ return spec.provides?.filter((s) => s.surface === "workflow").map((s) => s.key) ?? [];
74
+ }
75
+ /** Get all resource keys provided by a capability. */
76
+ getResourcesFor(capabilityKey$1, version) {
77
+ const spec = this.get(capabilityKey$1, version);
78
+ if (!spec) return [];
79
+ return spec.provides?.filter((s) => s.surface === "resource").map((s) => s.key) ?? [];
80
+ }
81
+ /** Get capability refs that provide a specific operation. */
82
+ getCapabilitiesForOperation(operationKey) {
83
+ const capKeys = this.buildSurfaceIndex().get(`operation:${operationKey}`);
84
+ if (!capKeys) return [];
85
+ return [...capKeys].map((k) => {
86
+ const spec = this.items.get(k);
87
+ return {
88
+ key: spec?.meta.key ?? "",
89
+ version: spec?.meta.version ?? ""
90
+ };
91
+ });
92
+ }
93
+ /** Get capability refs that provide a specific event. */
94
+ getCapabilitiesForEvent(eventKey) {
95
+ const capKeys = this.buildSurfaceIndex().get(`event:${eventKey}`);
96
+ if (!capKeys) return [];
97
+ return [...capKeys].map((k) => {
98
+ const spec = this.items.get(k);
99
+ return {
100
+ key: spec?.meta.key ?? "",
101
+ version: spec?.meta.version ?? ""
102
+ };
103
+ });
104
+ }
105
+ /** Get capability refs that provide a specific presentation. */
106
+ getCapabilitiesForPresentation(presentationKey) {
107
+ const capKeys = this.buildSurfaceIndex().get(`presentation:${presentationKey}`);
108
+ if (!capKeys) return [];
109
+ return [...capKeys].map((k) => {
110
+ const spec = this.items.get(k);
111
+ return {
112
+ key: spec?.meta.key ?? "",
113
+ version: spec?.meta.version ?? ""
114
+ };
115
+ });
116
+ }
117
+ /** Get the ancestor chain for a capability (from immediate parent to root). */
118
+ getAncestors(capabilityKey$1, version) {
119
+ const ancestors = [];
120
+ const visited = /* @__PURE__ */ new Set();
121
+ let current = this.get(capabilityKey$1, version);
122
+ while (current?.extends) {
123
+ const parentKey = capKey(current.extends.key, current.extends.version);
124
+ if (visited.has(parentKey)) break;
125
+ visited.add(parentKey);
126
+ const parent = this.get(current.extends.key, current.extends.version);
127
+ if (!parent) break;
128
+ ancestors.push(parent);
129
+ current = parent;
130
+ }
131
+ return ancestors;
132
+ }
133
+ /**
134
+ * Get effective requirements for a capability, including inherited ones.
135
+ * Requirements from ancestors are included, with child requirements taking
136
+ * precedence over parent requirements for the same key.
137
+ */
138
+ getEffectiveRequirements(capabilityKey$1, version) {
139
+ const spec = this.get(capabilityKey$1, version);
140
+ if (!spec) return [];
141
+ const ancestors = this.getAncestors(capabilityKey$1, version);
142
+ const requirementMap = /* @__PURE__ */ new Map();
143
+ for (const ancestor of [...ancestors].reverse()) for (const req of ancestor.requires ?? []) requirementMap.set(req.key, req);
144
+ for (const req of spec.requires ?? []) requirementMap.set(req.key, req);
145
+ return [...requirementMap.values()];
146
+ }
147
+ /**
148
+ * Get all surfaces provided by a capability, including inherited ones.
149
+ */
150
+ getEffectiveSurfaces(capabilityKey$1, version) {
151
+ const spec = this.get(capabilityKey$1, version);
152
+ if (!spec) return [];
153
+ const ancestors = this.getAncestors(capabilityKey$1, version);
154
+ const surfaces = [];
155
+ for (const ancestor of [...ancestors].reverse()) surfaces.push(...ancestor.provides ?? []);
156
+ surfaces.push(...spec.provides ?? []);
157
+ return surfaces;
158
+ }
34
159
  };
35
160
  function matchesRequirement(ref, requirement) {
36
161
  if (ref.key !== requirement.key) return false;
@@ -0,0 +1,88 @@
1
+ import { CapabilityRef } from "./capabilities.js";
2
+
3
+ //#region src/capabilities/context.d.ts
4
+
5
+ /**
6
+ * Error thrown when a required capability is missing.
7
+ */
8
+ declare class CapabilityMissingError extends Error {
9
+ readonly capabilityKey: string;
10
+ readonly requiredVersion?: string;
11
+ constructor(capabilityKey: string, requiredVersion?: string);
12
+ }
13
+ /**
14
+ * Runtime context for checking capability access.
15
+ *
16
+ * Created from a list of enabled capabilities (e.g., from user subscription,
17
+ * tenant config, or feature flags). Provides methods to check and require
18
+ * capabilities at runtime.
19
+ */
20
+ interface CapabilityContext {
21
+ /** Set of enabled capability keys (without version). */
22
+ readonly capabilities: ReadonlySet<string>;
23
+ /** Map of capability key to version for version-specific checks. */
24
+ readonly capabilityVersions: ReadonlyMap<string, string>;
25
+ /**
26
+ * Check if a capability is enabled.
27
+ * @param key - Capability key to check
28
+ * @param version - Optional specific version to require
29
+ * @returns True if capability is enabled
30
+ */
31
+ hasCapability(key: string, version?: string): boolean;
32
+ /**
33
+ * Require a capability, throwing if not enabled.
34
+ * @param key - Capability key to require
35
+ * @param version - Optional specific version to require
36
+ * @throws {CapabilityMissingError} If capability is not enabled
37
+ */
38
+ requireCapability(key: string, version?: string): void;
39
+ /**
40
+ * Check if all specified capabilities are enabled.
41
+ * @param keys - Array of capability keys to check
42
+ * @returns True if all capabilities are enabled
43
+ */
44
+ hasAllCapabilities(keys: string[]): boolean;
45
+ /**
46
+ * Check if any of the specified capabilities are enabled.
47
+ * @param keys - Array of capability keys to check
48
+ * @returns True if at least one capability is enabled
49
+ */
50
+ hasAnyCapability(keys: string[]): boolean;
51
+ /**
52
+ * Get enabled capabilities matching a pattern.
53
+ * @param pattern - Glob-like pattern (supports * wildcard)
54
+ * @returns Array of matching capability keys
55
+ */
56
+ getMatchingCapabilities(pattern: string): string[];
57
+ }
58
+ /**
59
+ * Creates a capability context from enabled capabilities.
60
+ *
61
+ * @param enabledCapabilities - Array of capability refs that are enabled
62
+ * @returns CapabilityContext for checking/requiring capabilities
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * // From user subscription capabilities
67
+ * const userCaps = await getUserCapabilities(userId);
68
+ * const ctx = createCapabilityContext(userCaps);
69
+ *
70
+ * // In handler
71
+ * ctx.requireCapability('premium-features');
72
+ * ```
73
+ */
74
+ declare function createCapabilityContext(enabledCapabilities: CapabilityRef[]): CapabilityContext;
75
+ /**
76
+ * Creates an empty capability context (no capabilities enabled).
77
+ * Useful for anonymous users or testing.
78
+ */
79
+ declare function createEmptyCapabilityContext(): CapabilityContext;
80
+ /**
81
+ * Creates a capability context with all capabilities enabled (bypass).
82
+ * Useful for admin users or internal services.
83
+ *
84
+ * @param allCapabilities - Array of all capability refs to enable
85
+ */
86
+ declare function createBypassCapabilityContext(allCapabilities: CapabilityRef[]): CapabilityContext;
87
+ //#endregion
88
+ export { CapabilityContext, CapabilityMissingError, createBypassCapabilityContext, createCapabilityContext, createEmptyCapabilityContext };
@@ -0,0 +1,87 @@
1
+ //#region src/capabilities/context.ts
2
+ /**
3
+ * Error thrown when a required capability is missing.
4
+ */
5
+ var CapabilityMissingError = class extends Error {
6
+ capabilityKey;
7
+ requiredVersion;
8
+ constructor(capabilityKey, requiredVersion) {
9
+ const versionSuffix = requiredVersion ? `.v${requiredVersion}` : "";
10
+ super(`Missing required capability: ${capabilityKey}${versionSuffix}`);
11
+ this.name = "CapabilityMissingError";
12
+ this.capabilityKey = capabilityKey;
13
+ this.requiredVersion = requiredVersion;
14
+ }
15
+ };
16
+ var CapabilityContextImpl = class {
17
+ capabilities;
18
+ capabilityVersions;
19
+ constructor(enabledCapabilities) {
20
+ const capSet = /* @__PURE__ */ new Set();
21
+ const versionMap = /* @__PURE__ */ new Map();
22
+ for (const cap of enabledCapabilities) {
23
+ capSet.add(cap.key);
24
+ versionMap.set(cap.key, cap.version);
25
+ }
26
+ this.capabilities = capSet;
27
+ this.capabilityVersions = versionMap;
28
+ }
29
+ hasCapability(key, version) {
30
+ if (!this.capabilities.has(key)) return false;
31
+ if (version != null) return this.capabilityVersions.get(key) === version;
32
+ return true;
33
+ }
34
+ requireCapability(key, version) {
35
+ if (!this.hasCapability(key, version)) throw new CapabilityMissingError(key, version);
36
+ }
37
+ hasAllCapabilities(keys) {
38
+ return keys.every((k) => this.capabilities.has(k));
39
+ }
40
+ hasAnyCapability(keys) {
41
+ return keys.some((k) => this.capabilities.has(k));
42
+ }
43
+ getMatchingCapabilities(pattern) {
44
+ if (!pattern.includes("*")) return this.capabilities.has(pattern) ? [pattern] : [];
45
+ const regexPattern = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
46
+ const regex = /* @__PURE__ */ new RegExp(`^${regexPattern}$`);
47
+ return [...this.capabilities].filter((key) => regex.test(key));
48
+ }
49
+ };
50
+ /**
51
+ * Creates a capability context from enabled capabilities.
52
+ *
53
+ * @param enabledCapabilities - Array of capability refs that are enabled
54
+ * @returns CapabilityContext for checking/requiring capabilities
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // From user subscription capabilities
59
+ * const userCaps = await getUserCapabilities(userId);
60
+ * const ctx = createCapabilityContext(userCaps);
61
+ *
62
+ * // In handler
63
+ * ctx.requireCapability('premium-features');
64
+ * ```
65
+ */
66
+ function createCapabilityContext(enabledCapabilities) {
67
+ return new CapabilityContextImpl(enabledCapabilities);
68
+ }
69
+ /**
70
+ * Creates an empty capability context (no capabilities enabled).
71
+ * Useful for anonymous users or testing.
72
+ */
73
+ function createEmptyCapabilityContext() {
74
+ return new CapabilityContextImpl([]);
75
+ }
76
+ /**
77
+ * Creates a capability context with all capabilities enabled (bypass).
78
+ * Useful for admin users or internal services.
79
+ *
80
+ * @param allCapabilities - Array of all capability refs to enable
81
+ */
82
+ function createBypassCapabilityContext(allCapabilities) {
83
+ return new CapabilityContextImpl(allCapabilities);
84
+ }
85
+
86
+ //#endregion
87
+ export { CapabilityMissingError, createBypassCapabilityContext, createCapabilityContext, createEmptyCapabilityContext };
@@ -4,7 +4,7 @@ import { registerDocBlocks } from "../../docs/registry.js";
4
4
  const tech_contracts_capabilities_DocBlocks = [{
5
5
  id: "docs.tech.contracts.capabilities",
6
6
  title: "CapabilitySpec Overview",
7
- summary: "Capability specs provide a canonical, versioned contract for what a module offers (`provides`) and what it depends on (`requires`). They enable safe composition across features, automated validation during `installFeature`, and consistent documentation for shared surfaces (APIs, events, workflows, UI, resources).",
7
+ summary: "Capability specs define what a module provides (operations, events, presentations) and requires (dependencies). They enable bidirectional linking, inheritance, runtime enforcement, and automated validation.",
8
8
  kind: "reference",
9
9
  visibility: "public",
10
10
  route: "/docs/tech/contracts/capabilities",
@@ -13,7 +13,196 @@ const tech_contracts_capabilities_DocBlocks = [{
13
13
  "contracts",
14
14
  "capabilities"
15
15
  ],
16
- body: "# CapabilitySpec Overview\n\n## Purpose\n\nCapability specs provide a canonical, versioned contract for what a module offers (`provides`) and what it depends on (`requires`). They enable safe composition across features, automated validation during `installFeature`, and consistent documentation for shared surfaces (APIs, events, workflows, UI, resources).\n\n## Schema\n\nDefined in `@contractspec/lib.contracts/src/capabilities.ts`.\n\n```ts\nexport interface CapabilitySpec {\n meta: CapabilityMeta; // ownership metadata + { key, version, kind }\n provides?: CapabilitySurfaceRef[]; // what concrete surfaces this capability exposes\n requires?: CapabilityRequirement[];// capabilities that must already exist\n}\n```\n\n- **CapabilityMeta**\n - `key`: stable slug (e.g., `payments.stripe`)\n - `version`: bump on breaking changes\n - `kind`: `'api' | 'event' | 'data' | 'ui' | 'integration'`\n - ownership fields (`title`, `description`, `domain`, `owners`, `tags`, `stability`)\n- **CapabilitySurfaceRef**\n - `surface`: `'operation' | 'event' | 'workflow' | 'presentation' | 'resource'`\n - `name` / `version`: points to the declared contract (operation name, event name, etc.)\n - optional `description`\n- **CapabilityRequirement**\n - `key`: capability slug to satisfy\n - `version?`: pin to an exact version when required (defaults to highest registered)\n - `kind?`: extra guard if the same key hosts multiple kinds\n - `optional?`: skip strict enforcement (informational requirement)\n - `reason?`: why this dependency exists (docs + tooling)\n\n## Registry\n\n`CapabilityRegistry` provides:\n\n- `register(spec)`: register a capability (`key + version` must be unique)\n- `get(key, version?)`: retrieve the exact or highest version\n- `list()`: inspect all capabilities\n- `satisfies(requirement, additional?)`: check if a requirement is met (includes locally provided capabilities passed via `additional`)\n\n## Feature Integration\n\n`FeatureModuleSpec` now accepts:\n\n```ts\ncapabilities?: {\n provides?: CapabilityRef[]; // capabilities this feature exposes\n requires?: CapabilityRequirement[]; // capabilities the feature needs\n};\n```\n\nDuring `installFeature`:\n\n1. `provides` entries must exist in the `CapabilityRegistry`.\n2. `requires` entries must be satisfied either by:\n - the same feature’s `provides`,\n - or existing capabilities already registered in the global registry.\n\nErrors are thrown when dependencies cannot be satisfied, preventing unsafe module composition.\n\n## Authoring Guidelines\n\n1. **Register capability specs** in a shared package (e.g., `packages/.../capabilities`) before referencing them in features.\n2. **Version consciously**: bump capability versions when the provided surfaces or contract semantics change.\n3. **Document dependencies** via `reason` strings to help operators understand why a capability is required.\n4. **Prefer stable keys** that map to business/technical domains (`billing.invoices`, `payments.stripe`, `cms.assets`).\n5. When introducing new capability kinds, update the `CapabilityKind` union and accompanying docs/tests.\n\n## Tooling (Roadmap)\n\n- CLI validation warns when feature specs reference missing capabilities.\n- Future build steps will leverage capability data to scaffold adapters and enforce policy in generated code.\n- Capability metadata will surface in docs/LLM guides to describe module marketplaces and installation flows.\n\n"
16
+ body: `# CapabilitySpec Overview
17
+
18
+ ## Purpose
19
+
20
+ Capabilities are **module interfaces** that define:
21
+ 1. What operations, events, and presentations a module exposes (\`provides\`)
22
+ 2. What other capabilities it depends on (\`requires\`)
23
+ 3. Inheritance hierarchies via \`extends\`
24
+
25
+ They enable:
26
+ - **Bidirectional linking**: Specs reference capabilities, capabilities list their specs
27
+ - **Dependency validation**: Features can't install without satisfying requirements
28
+ - **Runtime enforcement**: Check capabilities before executing operations
29
+ - **Inheritance**: Build capability hierarchies with shared requirements
30
+
31
+ ## Schema
32
+
33
+ \`\`\`ts
34
+ export interface CapabilitySpec {
35
+ meta: CapabilityMeta; // ownership metadata + { key, version, kind }
36
+ extends?: CapabilityRef; // NEW: inherit from parent capability
37
+ provides?: CapabilitySurfaceRef[]; // surfaces this capability exposes
38
+ requires?: CapabilityRequirement[];// capabilities that must exist
39
+ }
40
+ \`\`\`
41
+
42
+ ### Bidirectional Linking
43
+
44
+ Operations, events, and presentations can now declare their capability:
45
+
46
+ \`\`\`ts
47
+ // In OperationSpec
48
+ {
49
+ meta: { key: 'payments.charge.create', ... },
50
+ capability: { key: 'payments', version: '1.0.0' }, // Links to capability
51
+ io: { ... }
52
+ }
53
+
54
+ // In CapabilitySpec
55
+ {
56
+ meta: { key: 'payments', version: '1.0.0', ... },
57
+ provides: [
58
+ { surface: 'operation', key: 'payments.charge.create' }
59
+ ]
60
+ }
61
+ \`\`\`
62
+
63
+ Validation ensures both sides match via \`validateCapabilityConsistency()\`.
64
+
65
+ ## Registry Query Methods
66
+
67
+ The \`CapabilityRegistry\` now provides rich query capabilities:
68
+
69
+ \`\`\`ts
70
+ // Forward lookups: Capability → Specs
71
+ registry.getOperationsFor('payments'); // ['payments.charge.create', ...]
72
+ registry.getEventsFor('payments'); // ['payments.charge.succeeded', ...]
73
+ registry.getPresentationsFor('payments'); // ['payments.dashboard', ...]
74
+
75
+ // Reverse lookups: Spec → Capabilities
76
+ registry.getCapabilitiesForOperation('payments.charge.create');
77
+ registry.getCapabilitiesForEvent('payments.charge.succeeded');
78
+ registry.getCapabilitiesForPresentation('payments.dashboard');
79
+
80
+ // Inheritance
81
+ registry.getAncestors('payments.stripe'); // Parent chain
82
+ registry.getEffectiveRequirements('payments.stripe'); // Includes inherited
83
+ registry.getEffectiveSurfaces('payments.stripe'); // Includes inherited
84
+ \`\`\`
85
+
86
+ ## Inheritance
87
+
88
+ Capabilities can extend other capabilities:
89
+
90
+ \`\`\`ts
91
+ // Base capability
92
+ defineCapability({
93
+ meta: { key: 'payments.base', version: '1.0.0', ... },
94
+ requires: [{ key: 'auth', version: '1.0.0' }],
95
+ provides: [{ surface: 'operation', key: 'payments.list' }]
96
+ });
97
+
98
+ // Child capability inherits requirements
99
+ defineCapability({
100
+ meta: { key: 'payments.stripe', version: '1.0.0', ... },
101
+ extends: { key: 'payments.base', version: '1.0.0' },
102
+ requires: [{ key: 'encryption', version: '1.0.0' }], // Added
103
+ provides: [{ surface: 'operation', key: 'payments.stripe.charge' }]
104
+ });
105
+
106
+ // getEffectiveRequirements('payments.stripe') returns:
107
+ // [{ key: 'auth', ... }, { key: 'encryption', ... }]
108
+ \`\`\`
109
+
110
+ ## Runtime Enforcement
111
+
112
+ Use \`CapabilityContext\` for opt-in runtime checks:
113
+
114
+ \`\`\`ts
115
+ import { createCapabilityContext, assertCapabilityForOperation } from '@contractspec/lib.contracts';
116
+
117
+ // Create context from user's enabled capabilities
118
+ const ctx = createCapabilityContext(user.capabilities);
119
+
120
+ // Check capability
121
+ if (ctx.hasCapability('payments')) {
122
+ // User can access payments features
123
+ }
124
+
125
+ // Assert capability (throws if missing)
126
+ ctx.requireCapability('payments');
127
+
128
+ // Guard an operation
129
+ assertCapabilityForOperation(ctx, paymentOperation);
130
+
131
+ // Filter operations by enabled capabilities
132
+ const allowedOps = filterOperationsByCapability(ctx, allOperations);
133
+ \`\`\`
134
+
135
+ ## Validation
136
+
137
+ Validate bidirectional consistency between capabilities and specs:
138
+
139
+ \`\`\`ts
140
+ import { validateCapabilityConsistency, findOrphanSpecs } from '@contractspec/lib.contracts';
141
+
142
+ const result = validateCapabilityConsistency({
143
+ capabilities: capabilityRegistry,
144
+ operations: operationRegistry,
145
+ events: eventRegistry,
146
+ presentations: presentationRegistry,
147
+ });
148
+
149
+ if (!result.valid) {
150
+ console.error('Validation errors:', result.errors);
151
+ }
152
+
153
+ // Find specs without capability assignment (informational)
154
+ const orphans = findOrphanSpecs({ capabilities, operations });
155
+ \`\`\`
156
+
157
+ ## Feature Integration
158
+
159
+ During \`installFeature()\`:
160
+ 1. \`provides\` capabilities must exist in the registry
161
+ 2. \`requires\` must be satisfied by registered capabilities or local \`provides\`
162
+ 3. Referenced operations/events/presentations must exist
163
+
164
+ ## Authoring Guidelines
165
+
166
+ 1. **Register capabilities first** before referencing them in features
167
+ 2. **Use bidirectional linking** - set \`capability\` on specs and list them in \`provides\`
168
+ 3. **Version consciously** - bump versions on breaking changes
169
+ 4. **Document dependencies** with \`reason\` strings
170
+ 5. **Use inheritance** for capability families with shared requirements
171
+ 6. **Validate during CI** with \`validateCapabilityConsistency()\`
172
+
173
+ ## Error Handling
174
+
175
+ \`\`\`ts
176
+ import { CapabilityMissingError } from '@contractspec/lib.contracts';
177
+
178
+ try {
179
+ ctx.requireCapability('premium-features');
180
+ } catch (err) {
181
+ if (err instanceof CapabilityMissingError) {
182
+ console.log('Missing:', err.capabilityKey);
183
+ console.log('Required version:', err.requiredVersion);
184
+ }
185
+ }
186
+ \`\`\`
187
+
188
+ ## API Reference
189
+
190
+ ### Types
191
+ - \`CapabilitySpec\` - Capability definition
192
+ - \`CapabilityRef\` - Reference to a capability (key + version)
193
+ - \`CapabilitySurfaceRef\` - Reference to a provided surface
194
+ - \`CapabilityRequirement\` - Dependency requirement
195
+ - \`CapabilityContext\` - Runtime capability context
196
+ - \`CapabilityValidationResult\` - Validation result
197
+
198
+ ### Functions
199
+ - \`defineCapability(spec)\` - Define a capability spec
200
+ - \`createCapabilityContext(caps)\` - Create runtime context
201
+ - \`validateCapabilityConsistency(deps)\` - Validate bidirectional links
202
+ - \`findOrphanSpecs(deps)\` - Find specs without capability assignment
203
+ - \`assertCapabilityForOperation/Event/Presentation(ctx, spec)\` - Guards
204
+ - \`filterOperationsByCapability(ctx, ops)\` - Filter by enabled capabilities
205
+ `
17
206
  }];
18
207
  registerDocBlocks(tech_contracts_capabilities_DocBlocks);
19
208