@contractspec/lib.contracts 1.48.1 → 1.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/app-config/contracts.d.ts +50 -50
  2. package/dist/app-config/events.d.ts +27 -27
  3. package/dist/app-config/lifecycle-contracts.d.ts +54 -54
  4. package/dist/capabilities/capabilities.d.ts +27 -4
  5. package/dist/contract-registry/schemas.d.ts +4 -4
  6. package/dist/data-views/data-views.d.ts +2 -1
  7. package/dist/data-views/index.d.ts +2 -1
  8. package/dist/data-views/spec.d.ts +2 -8
  9. package/dist/events.d.ts +73 -13
  10. package/dist/events.js +33 -3
  11. package/dist/examples/schema.d.ts +14 -14
  12. package/dist/experiments/spec.d.ts +7 -4
  13. package/dist/features/index.d.ts +2 -2
  14. package/dist/features/types.d.ts +25 -29
  15. package/dist/index.d.ts +10 -6
  16. package/dist/index.js +3 -1
  17. package/dist/integrations/openbanking/contracts/accounts.d.ts +66 -66
  18. package/dist/integrations/openbanking/contracts/balances.d.ts +34 -34
  19. package/dist/integrations/openbanking/contracts/transactions.d.ts +48 -48
  20. package/dist/integrations/openbanking/models.d.ts +55 -55
  21. package/dist/integrations/operations.d.ts +102 -102
  22. package/dist/knowledge/operations.d.ts +66 -66
  23. package/dist/onboarding-base.d.ts +29 -29
  24. package/dist/ownership.d.ts +133 -8
  25. package/dist/ownership.js +25 -0
  26. package/dist/policy/spec.d.ts +7 -4
  27. package/dist/serialization/index.d.ts +3 -0
  28. package/dist/serialization/index.js +3 -0
  29. package/dist/serialization/serializers.d.ts +40 -0
  30. package/dist/serialization/serializers.js +148 -0
  31. package/dist/serialization/types.d.ts +103 -0
  32. package/dist/serialization/types.js +0 -0
  33. package/dist/tests/spec.d.ts +17 -12
  34. package/dist/themes.d.ts +7 -4
  35. package/dist/types.d.ts +140 -14
  36. package/dist/versioning/index.d.ts +2 -1
  37. package/dist/versioning/index.js +2 -1
  38. package/dist/versioning/refs.d.ts +179 -0
  39. package/dist/versioning/refs.js +161 -0
  40. package/dist/workflow/index.d.ts +2 -1
  41. package/dist/workflow/spec.d.ts +2 -9
  42. package/package.json +9 -5
package/dist/types.d.ts CHANGED
@@ -9,83 +9,209 @@ import { SpecVariantResolver } from "./experiments/spec-resolver.js";
9
9
  import { EventRegistry } from "./events.js";
10
10
 
11
11
  //#region src/types.d.ts
12
+
13
+ /**
14
+ * Common runtime types for ContractSpec execution.
15
+ *
16
+ * Provides types for execution context, policy decisions, event emission,
17
+ * and handler context passed through the contracts runtime.
18
+ *
19
+ * @module types
20
+ */
12
21
  /**
13
- * Common runtime types: execution context, policy decision & event emission.
22
+ * Actor type representing the entity making a request.
23
+ *
24
+ * - `anonymous`: Unauthenticated request
25
+ * - `user`: Authenticated end-user
26
+ * - `admin`: Administrative/system user with elevated privileges
14
27
  */
15
28
  type Actor = 'anonymous' | 'user' | 'admin';
29
+ /**
30
+ * Channel through which a request originates.
31
+ *
32
+ * - `web`: Browser/web application
33
+ * - `mobile`: Native mobile application
34
+ * - `job`: Background job/scheduled task
35
+ * - `agent`: AI agent or automated system
36
+ */
16
37
  type Channel = 'web' | 'mobile' | 'job' | 'agent';
38
+ /**
39
+ * Discriminator for all ContractSpec specification types.
40
+ *
41
+ * Used to identify the kind of spec in registries and runtime operations.
42
+ */
17
43
  type ContractSpecType = 'app-config' | 'agent' | 'operation' | 'example' | 'event' | 'presentation' | 'capability' | 'integration' | 'data-view' | 'feature' | 'workflow' | 'policy' | 'theme' | 'telemetry' | 'experiment' | 'knowledge-space';
44
+ /**
45
+ * Decision for a specific field access.
46
+ * Used for fine-grained field-level authorization.
47
+ */
18
48
  interface FieldLevelDecision {
49
+ /** The field path being evaluated. */
19
50
  field: string;
51
+ /** Whether access is allowed or denied. */
20
52
  effect: 'allow' | 'deny';
53
+ /** Human-readable reason for the decision. */
21
54
  reason?: string;
22
55
  }
56
+ /**
57
+ * Result of a policy evaluation.
58
+ *
59
+ * Contains the access decision and any applicable constraints
60
+ * like rate limits, escalation requirements, or consent needs.
61
+ */
23
62
  interface PolicyDecision {
63
+ /** Overall access decision: allow or deny. */
24
64
  effect: 'allow' | 'deny';
65
+ /** Human-readable reason for the decision. */
25
66
  reason?: string;
67
+ /** Rate limit constraints to apply if allowed. */
26
68
  rateLimit?: Pick<RateLimitDefinition, 'rpm' | 'key' | 'windowSeconds' | 'burst'>;
69
+ /** Escalation requirement for manual review. */
27
70
  escalate?: 'human_review' | null;
71
+ /** Per-field access decisions. */
28
72
  fieldDecisions?: FieldLevelDecision[];
73
+ /** PII handling policy. */
29
74
  pii?: PolicySpec['pii'];
75
+ /** Consents required before proceeding. */
30
76
  requiredConsents?: ConsentDefinition[];
77
+ /** Which engine produced this decision. */
31
78
  evaluatedBy?: 'engine' | 'opa';
32
79
  }
80
+ /**
81
+ * Input for policy evaluation.
82
+ * Contains context about the request being authorized.
83
+ */
33
84
  interface PolicyDeciderInput {
85
+ /** Service name (e.g., "sigil"). */
34
86
  service: string;
87
+ /** Command/operation name (e.g., "beginSignup"). */
35
88
  command: string;
89
+ /** Operation version. */
36
90
  version: string;
91
+ /** Actor type making the request. */
37
92
  actor: Actor;
93
+ /** Channel the request came from. */
38
94
  channel?: Channel;
95
+ /** Roles assigned to the actor. */
39
96
  roles?: string[];
97
+ /** Organization context if applicable. */
40
98
  organizationId?: string | null;
99
+ /** User context if authenticated. */
41
100
  userId?: string | null;
101
+ /** Active feature flags. */
42
102
  flags?: string[];
43
103
  }
104
+ /**
105
+ * Function that evaluates policy rules and returns a decision.
106
+ */
44
107
  type PolicyDecider = (input: PolicyDeciderInput) => Promise<PolicyDecision>;
108
+ /**
109
+ * Function that enforces rate limits.
110
+ *
111
+ * @param key - The rate limit key (e.g., user ID, IP)
112
+ * @param cost - Cost of this request (usually 1)
113
+ * @param rpm - Requests per minute limit
114
+ * @throws When rate limit is exceeded
115
+ */
45
116
  type RateLimiter = (key: string, cost: number, rpm: number) => Promise<void>;
117
+ /**
118
+ * Function that resolves translation keys to localized strings.
119
+ */
46
120
  type TranslationResolver = (key: MessageKey, locale?: Locale) => Promise<string | null> | string | null;
47
- /** Outbox/bus event publisher (after validation & guarding) */
121
+ /**
122
+ * Function that publishes events to the outbox/message bus.
123
+ * Called after validation and guard checks pass.
124
+ */
48
125
  type EventPublisher = (envelope: {
126
+ /** Event key (e.g., "user.created"). */
49
127
  key: string;
128
+ /** Event version. */
50
129
  version: string;
130
+ /** Validated event payload. */
51
131
  payload: unknown;
132
+ /** Trace ID for correlation. */
52
133
  traceId?: string;
53
134
  }) => Promise<void>;
135
+ /**
136
+ * Execution context passed to operation handlers.
137
+ *
138
+ * Contains all contextual information and service hooks needed
139
+ * during operation execution, including auth context, policy evaluation,
140
+ * telemetry, event publishing, and resolved configurations.
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * async function loginHandler(input: LoginInput, ctx: HandlerCtx) {
145
+ * // Check policy
146
+ * const decision = await ctx.decide?.({
147
+ * service: 'auth',
148
+ * command: 'login',
149
+ * version: '1.0.0',
150
+ * actor: ctx.actor ?? 'anonymous',
151
+ * });
152
+ *
153
+ * // Track telemetry
154
+ * ctx.telemetry?.track('login_attempt', { userId: ctx.userId });
155
+ *
156
+ * // Publish event
157
+ * await ctx.eventPublisher?.({
158
+ * key: 'user.loggedIn',
159
+ * version: '1.0.0',
160
+ * payload: { userId: input.email },
161
+ * traceId: ctx.traceId,
162
+ * });
163
+ * }
164
+ * ```
165
+ */
54
166
  interface HandlerCtx {
167
+ /** Distributed trace identifier for request correlation. */
55
168
  traceId?: string;
169
+ /** Idempotency key for deduplication. */
56
170
  idemKey?: string;
171
+ /** Organization context for multi-tenant operations. */
57
172
  organizationId?: string | null;
173
+ /** Authenticated user ID. */
58
174
  userId?: string | null;
175
+ /** Actor type making the request. */
59
176
  actor?: Actor;
177
+ /** Channel the request originated from. */
60
178
  channel?: Channel;
179
+ /** Roles assigned to the authenticated user. */
61
180
  roles?: string[];
62
- /** Policy engine hook (policy.yaml) */
181
+ /** Policy engine for authorization decisions. */
63
182
  decide?: PolicyDecider;
64
- /** Rate limiter (e.g., Redis) */
183
+ /** Rate limiter service (e.g., Redis-backed). */
65
184
  rateLimit?: RateLimiter;
66
- /** Telemetry tracker */
185
+ /** Telemetry tracker for metrics and events. */
67
186
  telemetry?: TelemetryTracker;
68
- /** Event publisher (outbox+bus) */
187
+ /** Event publisher for domain events (outbox/bus). */
69
188
  eventPublisher?: EventPublisher;
70
- /** Secret provider for secure credentials */
189
+ /** Secret provider for secure credential access. */
71
190
  secretProvider?: SecretProvider;
72
- /** Internal pipe: filled by executor to enforce declared events */
191
+ /**
192
+ * Internal emit guard for enforcing declared event emissions.
193
+ * Populated by the executor runtime.
194
+ * @internal
195
+ */
73
196
  __emitGuard__?: (key: string, version: string, payload: unknown) => Promise<void>;
74
- /** Resolved application configuration for the current execution context */
197
+ /** Resolved application configuration for this execution. */
75
198
  appConfig?: ResolvedAppConfig;
76
- /** Resolved integration connections available to this execution */
199
+ /** Resolved integration connections available to this execution. */
77
200
  integrations?: ResolvedIntegration[];
78
- /** Resolved knowledge spaces available to this execution */
201
+ /** Resolved knowledge spaces available to this execution. */
79
202
  knowledge?: ResolvedKnowledge[];
80
- /** Resolved branding context */
203
+ /** Resolved branding context (logos, colors, etc.). */
81
204
  branding?: ResolvedBranding;
82
- /** Translation context */
205
+ /** Translation context with config and resolver. */
83
206
  translation?: {
207
+ /** Resolved translation configuration. */
84
208
  config: ResolvedTranslation;
209
+ /** Function to resolve translation keys. */
85
210
  resolve?: TranslationResolver;
86
211
  };
87
- /** Optional spec variant resolver for experiments */
212
+ /** Spec variant resolver for A/B testing and experiments. */
88
213
  specVariantResolver?: SpecVariantResolver;
214
+ /** Event registry for runtime event spec lookup. */
89
215
  eventSpecResolver?: EventRegistry;
90
216
  }
91
217
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { OptionalVersionedSpecRef, SpecKeyRef, VersionedSpecRef, createKeyRef, createOptionalRef, createVersionedRef, formatVersionedRefKey, isOptionalVersionedSpecRef, isSpecKeyRef, isVersionedSpecRef, parseVersionedRefKey } from "./refs.js";
1
2
  import { ChangeEntry, ChangeType, ChangelogDocBlock, ChangelogEntry, ChangelogJsonExport, ChangelogResult, SemanticVersion, VersionAnalysis, VersionAnalysisResult, VersionBumpType, isChangeType, isChangelogDocBlock, isVersionBumpType } from "./types.js";
2
3
  import { bumpVersion, compareVersions, determineBumpType, formatVersion, getBumpTypePriority, getMaxBumpType, isValidVersion, isVersionEqual, isVersionGreater, isVersionLess, parseVersion, parseVersionStrict, validateVersion } from "./utils.js";
3
- export { ChangeEntry, ChangeType, ChangelogDocBlock, ChangelogEntry, ChangelogJsonExport, ChangelogResult, SemanticVersion, VersionAnalysis, VersionAnalysisResult, VersionBumpType, bumpVersion, compareVersions, determineBumpType, formatVersion, getBumpTypePriority, getMaxBumpType, isChangeType, isChangelogDocBlock, isValidVersion, isVersionBumpType, isVersionEqual, isVersionGreater, isVersionLess, parseVersion, parseVersionStrict, validateVersion };
4
+ export { ChangeEntry, ChangeType, ChangelogDocBlock, ChangelogEntry, ChangelogJsonExport, ChangelogResult, OptionalVersionedSpecRef, SemanticVersion, SpecKeyRef, VersionAnalysis, VersionAnalysisResult, VersionBumpType, VersionedSpecRef, bumpVersion, compareVersions, createKeyRef, createOptionalRef, createVersionedRef, determineBumpType, formatVersion, formatVersionedRefKey, getBumpTypePriority, getMaxBumpType, isChangeType, isChangelogDocBlock, isOptionalVersionedSpecRef, isSpecKeyRef, isValidVersion, isVersionBumpType, isVersionEqual, isVersionGreater, isVersionLess, isVersionedSpecRef, parseVersion, parseVersionStrict, parseVersionedRefKey, validateVersion };
@@ -1,4 +1,5 @@
1
+ import { createKeyRef, createOptionalRef, createVersionedRef, formatVersionedRefKey, isOptionalVersionedSpecRef, isSpecKeyRef, isVersionedSpecRef, parseVersionedRefKey } from "./refs.js";
1
2
  import { isChangeType, isChangelogDocBlock, isVersionBumpType } from "./types.js";
2
3
  import { bumpVersion, compareVersions, determineBumpType, formatVersion, getBumpTypePriority, getMaxBumpType, isValidVersion, isVersionEqual, isVersionGreater, isVersionLess, parseVersion, parseVersionStrict, validateVersion } from "./utils.js";
3
4
 
4
- export { bumpVersion, compareVersions, determineBumpType, formatVersion, getBumpTypePriority, getMaxBumpType, isChangeType, isChangelogDocBlock, isValidVersion, isVersionBumpType, isVersionEqual, isVersionGreater, isVersionLess, parseVersion, parseVersionStrict, validateVersion };
5
+ export { bumpVersion, compareVersions, createKeyRef, createOptionalRef, createVersionedRef, determineBumpType, formatVersion, formatVersionedRefKey, getBumpTypePriority, getMaxBumpType, isChangeType, isChangelogDocBlock, isOptionalVersionedSpecRef, isSpecKeyRef, isValidVersion, isVersionBumpType, isVersionEqual, isVersionGreater, isVersionLess, isVersionedSpecRef, parseVersion, parseVersionStrict, parseVersionedRefKey, validateVersion };
@@ -0,0 +1,179 @@
1
+ //#region src/versioning/refs.d.ts
2
+ /**
3
+ * Base reference types for ContractSpec versioning.
4
+ *
5
+ * Provides canonical reference types for linking between specs.
6
+ * Domain-specific refs (OpRef, EventRef, etc.) should alias these
7
+ * base types for consistency and maintainability.
8
+ *
9
+ * @module versioning/refs
10
+ */
11
+ /**
12
+ * Base reference type for versioned specs.
13
+ * Used to reference any spec by its key and version.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * const opRef: VersionedSpecRef = { key: 'auth.login', version: '1.0.0' };
18
+ * ```
19
+ */
20
+ interface VersionedSpecRef {
21
+ /** Unique key identifying the spec (e.g., "auth.login", "user.created"). */
22
+ key: string;
23
+ /** Semantic version of the spec (e.g., "1.0.0", "2.1.0"). */
24
+ version: string;
25
+ }
26
+ /**
27
+ * Base reference type for specs with optional version.
28
+ * When version is omitted, typically refers to the latest version.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Reference to latest version
33
+ * const latestRef: OptionalVersionedSpecRef = { key: 'auth.login' };
34
+ *
35
+ * // Reference to specific version
36
+ * const specificRef: OptionalVersionedSpecRef = { key: 'auth.login', version: '1.0.0' };
37
+ * ```
38
+ */
39
+ interface OptionalVersionedSpecRef {
40
+ /** Unique key identifying the spec. */
41
+ key: string;
42
+ /** Optional semantic version. When omitted, refers to the latest version. */
43
+ version?: string;
44
+ }
45
+ /**
46
+ * Base reference type for unversioned spec keys.
47
+ * Used when only the key is needed without version information.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const featureRef: SpecKeyRef = { key: 'premium-features' };
52
+ * ```
53
+ */
54
+ interface SpecKeyRef {
55
+ /** Unique key identifying the spec. */
56
+ key: string;
57
+ }
58
+ /**
59
+ * Checks if a value is a valid VersionedSpecRef.
60
+ *
61
+ * @param ref - The value to check
62
+ * @returns True if the value has both key and version as strings
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const ref = { key: 'auth.login', version: '1.0.0' };
67
+ * if (isVersionedSpecRef(ref)) {
68
+ * console.log(`Spec: ${ref.key}@${ref.version}`);
69
+ * }
70
+ * ```
71
+ */
72
+ declare function isVersionedSpecRef(ref: unknown): ref is VersionedSpecRef;
73
+ /**
74
+ * Checks if a value is a valid OptionalVersionedSpecRef.
75
+ *
76
+ * @param ref - The value to check
77
+ * @returns True if the value has a key string and optional version string
78
+ *
79
+ * @example
80
+ * ```typescript
81
+ * const ref = { key: 'auth.login' };
82
+ * if (isOptionalVersionedSpecRef(ref)) {
83
+ * console.log(`Spec: ${ref.key}${ref.version ? `@${ref.version}` : ''}`);
84
+ * }
85
+ * ```
86
+ */
87
+ declare function isOptionalVersionedSpecRef(ref: unknown): ref is OptionalVersionedSpecRef;
88
+ /**
89
+ * Checks if a value is a valid SpecKeyRef.
90
+ *
91
+ * @param ref - The value to check
92
+ * @returns True if the value has a key string
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const ref = { key: 'premium-features' };
97
+ * if (isSpecKeyRef(ref)) {
98
+ * console.log(`Feature: ${ref.key}`);
99
+ * }
100
+ * ```
101
+ */
102
+ declare function isSpecKeyRef(ref: unknown): ref is SpecKeyRef;
103
+ /**
104
+ * Creates a versioned spec reference.
105
+ *
106
+ * @param key - The spec key (e.g., "auth.login")
107
+ * @param version - The semantic version (e.g., "1.0.0")
108
+ * @returns A VersionedSpecRef object
109
+ * @throws {Error} If key or version is empty
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const ref = createVersionedRef('auth.login', '1.0.0');
114
+ * // { key: 'auth.login', version: '1.0.0' }
115
+ * ```
116
+ */
117
+ declare function createVersionedRef(key: string, version: string): VersionedSpecRef;
118
+ /**
119
+ * Creates an optional versioned spec reference.
120
+ *
121
+ * @param key - The spec key (e.g., "auth.login")
122
+ * @param version - Optional semantic version
123
+ * @returns An OptionalVersionedSpecRef object
124
+ * @throws {Error} If key is empty
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // Reference to latest version
129
+ * const latestRef = createOptionalRef('auth.login');
130
+ * // { key: 'auth.login' }
131
+ *
132
+ * // Reference to specific version
133
+ * const specificRef = createOptionalRef('auth.login', '1.0.0');
134
+ * // { key: 'auth.login', version: '1.0.0' }
135
+ * ```
136
+ */
137
+ declare function createOptionalRef(key: string, version?: string): OptionalVersionedSpecRef;
138
+ /**
139
+ * Creates a spec key reference.
140
+ *
141
+ * @param key - The spec key (e.g., "premium-features")
142
+ * @returns A SpecKeyRef object
143
+ * @throws {Error} If key is empty
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const ref = createKeyRef('premium-features');
148
+ * // { key: 'premium-features' }
149
+ * ```
150
+ */
151
+ declare function createKeyRef(key: string): SpecKeyRef;
152
+ /**
153
+ * Formats a versioned ref as a string key.
154
+ *
155
+ * @param ref - The versioned spec reference
156
+ * @returns A string in the format "key.vversion"
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * const str = formatVersionedRefKey({ key: 'auth.login', version: '1.0.0' });
161
+ * // "auth.login.v1.0.0"
162
+ * ```
163
+ */
164
+ declare function formatVersionedRefKey(ref: VersionedSpecRef): string;
165
+ /**
166
+ * Parses a versioned ref string back into a ref object.
167
+ *
168
+ * @param refKey - A string in the format "key.vversion"
169
+ * @returns A VersionedSpecRef or undefined if parsing fails
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * const ref = parseVersionedRefKey('auth.login.v1.0.0');
174
+ * // { key: 'auth.login', version: '1.0.0' }
175
+ * ```
176
+ */
177
+ declare function parseVersionedRefKey(refKey: string): VersionedSpecRef | undefined;
178
+ //#endregion
179
+ export { OptionalVersionedSpecRef, SpecKeyRef, VersionedSpecRef, createKeyRef, createOptionalRef, createVersionedRef, formatVersionedRefKey, isOptionalVersionedSpecRef, isSpecKeyRef, isVersionedSpecRef, parseVersionedRefKey };
@@ -0,0 +1,161 @@
1
+ //#region src/versioning/refs.ts
2
+ /**
3
+ * Checks if a value is a valid VersionedSpecRef.
4
+ *
5
+ * @param ref - The value to check
6
+ * @returns True if the value has both key and version as strings
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const ref = { key: 'auth.login', version: '1.0.0' };
11
+ * if (isVersionedSpecRef(ref)) {
12
+ * console.log(`Spec: ${ref.key}@${ref.version}`);
13
+ * }
14
+ * ```
15
+ */
16
+ function isVersionedSpecRef(ref) {
17
+ return typeof ref === "object" && ref !== null && "key" in ref && typeof ref.key === "string" && ref.key.length > 0 && "version" in ref && typeof ref.version === "string" && ref.version.length > 0;
18
+ }
19
+ /**
20
+ * Checks if a value is a valid OptionalVersionedSpecRef.
21
+ *
22
+ * @param ref - The value to check
23
+ * @returns True if the value has a key string and optional version string
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const ref = { key: 'auth.login' };
28
+ * if (isOptionalVersionedSpecRef(ref)) {
29
+ * console.log(`Spec: ${ref.key}${ref.version ? `@${ref.version}` : ''}`);
30
+ * }
31
+ * ```
32
+ */
33
+ function isOptionalVersionedSpecRef(ref) {
34
+ if (typeof ref !== "object" || ref === null) return false;
35
+ if (!("key" in ref)) return false;
36
+ if (typeof ref.key !== "string" || ref.key.length === 0) return false;
37
+ if ("version" in ref && ref.version != null) return typeof ref.version === "string";
38
+ return true;
39
+ }
40
+ /**
41
+ * Checks if a value is a valid SpecKeyRef.
42
+ *
43
+ * @param ref - The value to check
44
+ * @returns True if the value has a key string
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const ref = { key: 'premium-features' };
49
+ * if (isSpecKeyRef(ref)) {
50
+ * console.log(`Feature: ${ref.key}`);
51
+ * }
52
+ * ```
53
+ */
54
+ function isSpecKeyRef(ref) {
55
+ return typeof ref === "object" && ref !== null && "key" in ref && typeof ref.key === "string" && ref.key.length > 0;
56
+ }
57
+ /**
58
+ * Creates a versioned spec reference.
59
+ *
60
+ * @param key - The spec key (e.g., "auth.login")
61
+ * @param version - The semantic version (e.g., "1.0.0")
62
+ * @returns A VersionedSpecRef object
63
+ * @throws {Error} If key or version is empty
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const ref = createVersionedRef('auth.login', '1.0.0');
68
+ * // { key: 'auth.login', version: '1.0.0' }
69
+ * ```
70
+ */
71
+ function createVersionedRef(key, version) {
72
+ if (!key || key.trim().length === 0) throw new Error("Spec key cannot be empty");
73
+ if (!version || version.trim().length === 0) throw new Error("Spec version cannot be empty");
74
+ return {
75
+ key: key.trim(),
76
+ version: version.trim()
77
+ };
78
+ }
79
+ /**
80
+ * Creates an optional versioned spec reference.
81
+ *
82
+ * @param key - The spec key (e.g., "auth.login")
83
+ * @param version - Optional semantic version
84
+ * @returns An OptionalVersionedSpecRef object
85
+ * @throws {Error} If key is empty
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * // Reference to latest version
90
+ * const latestRef = createOptionalRef('auth.login');
91
+ * // { key: 'auth.login' }
92
+ *
93
+ * // Reference to specific version
94
+ * const specificRef = createOptionalRef('auth.login', '1.0.0');
95
+ * // { key: 'auth.login', version: '1.0.0' }
96
+ * ```
97
+ */
98
+ function createOptionalRef(key, version) {
99
+ if (!key || key.trim().length === 0) throw new Error("Spec key cannot be empty");
100
+ const ref = { key: key.trim() };
101
+ if (version != null && version.trim().length > 0) ref.version = version.trim();
102
+ return ref;
103
+ }
104
+ /**
105
+ * Creates a spec key reference.
106
+ *
107
+ * @param key - The spec key (e.g., "premium-features")
108
+ * @returns A SpecKeyRef object
109
+ * @throws {Error} If key is empty
110
+ *
111
+ * @example
112
+ * ```typescript
113
+ * const ref = createKeyRef('premium-features');
114
+ * // { key: 'premium-features' }
115
+ * ```
116
+ */
117
+ function createKeyRef(key) {
118
+ if (!key || key.trim().length === 0) throw new Error("Spec key cannot be empty");
119
+ return { key: key.trim() };
120
+ }
121
+ /**
122
+ * Formats a versioned ref as a string key.
123
+ *
124
+ * @param ref - The versioned spec reference
125
+ * @returns A string in the format "key.vversion"
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * const str = formatVersionedRefKey({ key: 'auth.login', version: '1.0.0' });
130
+ * // "auth.login.v1.0.0"
131
+ * ```
132
+ */
133
+ function formatVersionedRefKey(ref) {
134
+ return `${ref.key}.v${ref.version}`;
135
+ }
136
+ /**
137
+ * Parses a versioned ref string back into a ref object.
138
+ *
139
+ * @param refKey - A string in the format "key.vversion"
140
+ * @returns A VersionedSpecRef or undefined if parsing fails
141
+ *
142
+ * @example
143
+ * ```typescript
144
+ * const ref = parseVersionedRefKey('auth.login.v1.0.0');
145
+ * // { key: 'auth.login', version: '1.0.0' }
146
+ * ```
147
+ */
148
+ function parseVersionedRefKey(refKey) {
149
+ const match = refKey.match(/^(.+)\.v(\d+\.\d+\.\d+(?:-.+)?)$/);
150
+ if (!match) return void 0;
151
+ const key = match[1];
152
+ const version = match[2];
153
+ if (!key || !version) return void 0;
154
+ return {
155
+ key,
156
+ version
157
+ };
158
+ }
159
+
160
+ //#endregion
161
+ export { createKeyRef, createOptionalRef, createVersionedRef, formatVersionedRefKey, isOptionalVersionedSpecRef, isSpecKeyRef, isVersionedSpecRef, parseVersionedRefKey };
@@ -1,4 +1,5 @@
1
- import { CompensationStep, CompensationStrategy, FormRef, GuardCondition, GuardConditionKind, RetryPolicy, SLA, Step, StepAction, StepType, Transition, WorkflowDefinition, WorkflowMeta, WorkflowRegistry, WorkflowSpec, WorkflowStatus } from "./spec.js";
1
+ import { FormRef } from "../features/types.js";
2
+ import { CompensationStep, CompensationStrategy, GuardCondition, GuardConditionKind, RetryPolicy, SLA, Step, StepAction, StepType, Transition, WorkflowDefinition, WorkflowMeta, WorkflowRegistry, WorkflowSpec, WorkflowStatus } from "./spec.js";
2
3
  import { ValidateWorkflowSpecOptions, WorkflowValidationError, WorkflowValidationIssue, WorkflowValidationLevel, assertWorkflowSpecValid, validateWorkflowSpec } from "./validation.js";
3
4
  import { StateStore, StepExecution, WorkflowState, WorkflowStateFilters } from "./state.js";
4
5
  import { GuardContext, GuardEvaluator, OperationExecutor, OperationExecutorContext, WorkflowPreFlightError, WorkflowPreFlightIssue, WorkflowPreFlightIssueSeverity, WorkflowPreFlightIssueType, WorkflowPreFlightResult, WorkflowRunner, WorkflowRunnerConfig } from "./runner.js";
@@ -2,18 +2,11 @@ import { OwnerShipMeta } from "../ownership.js";
2
2
  import { CapabilityRef } from "../capabilities/capabilities.js";
3
3
  import "../capabilities/index.js";
4
4
  import { ExperimentRef } from "../experiments/spec.js";
5
- import { OpRef } from "../features/types.js";
5
+ import { FormRef, OpRef } from "../features/types.js";
6
6
  import "../features/index.js";
7
7
  import { SpecContractRegistry } from "../registry.js";
8
8
 
9
9
  //#region src/workflow/spec.d.ts
10
- /**
11
- * Reference to a form spec declared in {@link FormRegistry}.
12
- */
13
- interface FormRef {
14
- key: string;
15
- version: string;
16
- }
17
10
  type StepType = 'human' | 'automation' | 'decision';
18
11
  type WorkflowStatus = 'running' | 'paused' | 'completed' | 'failed' | 'cancelled';
19
12
  type GuardConditionKind = 'policy' | 'expression';
@@ -90,4 +83,4 @@ declare class WorkflowRegistry extends SpecContractRegistry<'workflow', Workflow
90
83
  constructor(items?: WorkflowSpec[]);
91
84
  }
92
85
  //#endregion
93
- export { CompensationStep, CompensationStrategy, FormRef, GuardCondition, GuardConditionKind, RetryPolicy, SLA, Step, StepAction, StepType, Transition, WorkflowDefinition, WorkflowMeta, WorkflowRegistry, WorkflowSpec, WorkflowStatus };
86
+ export { CompensationStep, CompensationStrategy, type FormRef, GuardCondition, GuardConditionKind, RetryPolicy, SLA, Step, StepAction, StepType, Transition, WorkflowDefinition, WorkflowMeta, WorkflowRegistry, WorkflowSpec, WorkflowStatus };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contractspec/lib.contracts",
3
- "version": "1.48.1",
3
+ "version": "1.50.0",
4
4
  "description": "Core contract specification definitions and runtime",
5
5
  "keywords": [
6
6
  "contractspec",
@@ -25,8 +25,8 @@
25
25
  "test": "bun test"
26
26
  },
27
27
  "devDependencies": {
28
- "@contractspec/tool.tsdown": "1.48.0",
29
- "@contractspec/tool.typescript": "1.48.0",
28
+ "@contractspec/tool.tsdown": "1.50.0",
29
+ "@contractspec/tool.typescript": "1.50.0",
30
30
  "@types/express": "^5.0.3",
31
31
  "@types/turndown": "^5.0.6",
32
32
  "tsdown": "^0.19.0",
@@ -35,8 +35,8 @@
35
35
  "dependencies": {
36
36
  "@aws-sdk/client-secrets-manager": "^3.966.0",
37
37
  "@aws-sdk/client-sqs": "^3.966.0",
38
- "@contractspec/lib.logger": "1.48.0",
39
- "@contractspec/lib.schema": "1.48.0",
38
+ "@contractspec/lib.logger": "1.50.0",
39
+ "@contractspec/lib.schema": "1.50.0",
40
40
  "@elevenlabs/elevenlabs-js": "^2.30.0",
41
41
  "@google-cloud/secret-manager": "^6.1.1",
42
42
  "@google-cloud/storage": "^7.18.0",
@@ -306,6 +306,9 @@
306
306
  "./registry-utils": "./dist/registry-utils.js",
307
307
  "./resources": "./dist/resources.js",
308
308
  "./schema-to-markdown": "./dist/schema-to-markdown.js",
309
+ "./serialization": "./dist/serialization/index.js",
310
+ "./serialization/serializers": "./dist/serialization/serializers.js",
311
+ "./serialization/types": "./dist/serialization/types.js",
309
312
  "./server": "./dist/server/index.js",
310
313
  "./server/contracts-adapter-hydration": "./dist/server/contracts-adapter-hydration.js",
311
314
  "./server/contracts-adapter-input": "./dist/server/contracts-adapter-input.js",
@@ -336,6 +339,7 @@
336
339
  "./translations/tenant": "./dist/translations/tenant.js",
337
340
  "./types": "./dist/types.js",
338
341
  "./versioning": "./dist/versioning/index.js",
342
+ "./versioning/refs": "./dist/versioning/refs.js",
339
343
  "./versioning/types": "./dist/versioning/types.js",
340
344
  "./versioning/utils": "./dist/versioning/utils.js",
341
345
  "./workflow": "./dist/workflow/index.js",