@rayspec/spec 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +105 -0
- package/dist/brace-params.d.ts +32 -0
- package/dist/brace-params.d.ts.map +1 -0
- package/dist/brace-params.js +89 -0
- package/dist/brace-params.js.map +1 -0
- package/dist/detect.d.ts +44 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/detect.js +72 -0
- package/dist/detect.js.map +1 -0
- package/dist/errors.d.ts +204 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +165 -0
- package/dist/errors.js.map +1 -0
- package/dist/export.d.ts +54 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +121 -0
- package/dist/export.js.map +1 -0
- package/dist/grammar.d.ts +569 -0
- package/dist/grammar.d.ts.map +1 -0
- package/dist/grammar.js +503 -0
- package/dist/grammar.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/lint.d.ts +79 -0
- package/dist/lint.d.ts.map +1 -0
- package/dist/lint.js +823 -0
- package/dist/lint.js.map +1 -0
- package/dist/parse.d.ts +8 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +118 -0
- package/dist/parse.js.map +1 -0
- package/dist/product-events.d.ts +73 -0
- package/dist/product-events.d.ts.map +1 -0
- package/dist/product-events.js +42 -0
- package/dist/product-events.js.map +1 -0
- package/dist/product-grammar.d.ts +948 -0
- package/dist/product-grammar.d.ts.map +1 -0
- package/dist/product-grammar.js +581 -0
- package/dist/product-grammar.js.map +1 -0
- package/dist/product-lint.d.ts +74 -0
- package/dist/product-lint.d.ts.map +1 -0
- package/dist/product-lint.js +821 -0
- package/dist/product-lint.js.map +1 -0
- package/dist/product-parse.d.ts +8 -0
- package/dist/product-parse.d.ts.map +1 -0
- package/dist/product-parse.js +119 -0
- package/dist/product-parse.js.map +1 -0
- package/dist/product-scope.d.ts +53 -0
- package/dist/product-scope.d.ts.map +1 -0
- package/dist/product-scope.js +55 -0
- package/dist/product-scope.js.map +1 -0
- package/dist/product-views-lint.d.ts +14 -0
- package/dist/product-views-lint.d.ts.map +1 -0
- package/dist/product-views-lint.js +669 -0
- package/dist/product-views-lint.js.map +1 -0
- package/dist/product-views.d.ts +426 -0
- package/dist/product-views.d.ts.map +1 -0
- package/dist/product-views.js +317 -0
- package/dist/product-views.js.map +1 -0
- package/package.json +34 -0
package/dist/grammar.js
ADDED
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The RaySpec config grammar — `RaySpec` and its six sections.
|
|
3
|
+
*
|
|
4
|
+
* A deployed backend is ONE validated `RaySpec` — stores · api · agents ·
|
|
5
|
+
* tooling · triggers · handlers. This module defines ONLY the Zod grammar (shape). The
|
|
6
|
+
* two-phase parser (`parse.ts`), the semantic linter (`lint.ts`), and the JSON-Schema exporter
|
|
7
|
+
* (`export.ts`) build on top of it.
|
|
8
|
+
*
|
|
9
|
+
* FAIL-CLOSED BY CONSTRUCTION: every GRAMMAR object level is `.strict()`, so an
|
|
10
|
+
* unknown key is rejected — there is no silent passthrough of a typo'd or unrecognized field.
|
|
11
|
+
* Verified (zod 4.4.3, doc-first probe): `.omit().extend().strict()` composes so the wrap layer
|
|
12
|
+
* stays strict AND the exported JSON-Schema carries `additionalProperties:false` at every STRICT
|
|
13
|
+
* grammar level. The THREE embedded JSON-Schema slots (a tool's `parameters`/`outputSchema` and an
|
|
14
|
+
* agent's `outputSchema.schema`) are intentionally OPEN records — they ARE free-form JSON-Schema,
|
|
15
|
+
* validated separately by ajv (lint.ts), not by strict-key rejection.
|
|
16
|
+
*
|
|
17
|
+
* HYBRID WRAP:
|
|
18
|
+
* - `agents[]` and `tooling[]` WRAP the neutral `core` types (`AgentSpec`/`ToolSpec`) — the
|
|
19
|
+
* literal interpreter input — so there is ONE source of truth for the neutral fields. Honest
|
|
20
|
+
* limit of the wrap: a neutral REMOVAL or RENAME surfaces LOUDLY (a `.omit()`/`.extend()` on a
|
|
21
|
+
* missing key is a compile error); a neutral ADDITION is ABSORBED SILENTLY into the grammar.
|
|
22
|
+
* The `AgentSpecConfig`/`ToolSpecConfig` shape-key PIN TESTS (grammar.test.ts) are what make an
|
|
23
|
+
* addition deliberate — a new neutral key fails the pin and forces a conscious spec-bump call.
|
|
24
|
+
* - `stores[]`, `api[]`, `triggers[]`, `handlers[]` are INDEPENDENT Zod types (no neutral
|
|
25
|
+
* precedent exists for them).
|
|
26
|
+
*
|
|
27
|
+
* RUNTIME vs CONFIG (load-bearing): `core.AgentSpec` includes `input` — that is the RUNTIME task
|
|
28
|
+
* value supplied per request, NOT config. A declared agent MUST OMIT it (we `.omit({ input })`),
|
|
29
|
+
* and supplies it at request time. Likewise `core.AgentSpec.tools` is an INLINE
|
|
30
|
+
* neutral-tool array; in the config layer an agent references declared `tooling[]` entries BY ID,
|
|
31
|
+
* so we omit the inline array and add an `id`-reference list (`tools: string[]`) instead. The
|
|
32
|
+
* lint pass resolves those references against the `tooling[]` section.
|
|
33
|
+
*/
|
|
34
|
+
import { BackendId, AgentSpec as NeutralAgentSpec, ToolSpec as NeutralToolSpec, } from '@rayspec/core';
|
|
35
|
+
import { z } from 'zod';
|
|
36
|
+
/** The supported spec major.minor. Parsed FIRST (two-phase) so an unknown major fails cleanly. */
|
|
37
|
+
export const SPEC_VERSION = '1.0';
|
|
38
|
+
// ---------------------------------------------------------------------------------------
|
|
39
|
+
// metadata
|
|
40
|
+
// ---------------------------------------------------------------------------------------
|
|
41
|
+
/** Minimal deployment metadata. `name` identifies the backend; extend later as needed. */
|
|
42
|
+
export const Metadata = z
|
|
43
|
+
.object({
|
|
44
|
+
name: z.string().min(1),
|
|
45
|
+
description: z.string().optional(),
|
|
46
|
+
})
|
|
47
|
+
.strict();
|
|
48
|
+
// ---------------------------------------------------------------------------------------
|
|
49
|
+
// deployment — independent grammar (deployment PROPERTY, not a backend capability)
|
|
50
|
+
// ---------------------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* Deployment-level properties of a backend. These describe HOW the
|
|
53
|
+
* deployment runs, NOT what any SDK can do — so `async`/off-request execution belongs HERE, on the
|
|
54
|
+
* spec, gated by "is a durable worker configured?", and is INVISIBLE to the neutral `Backend`
|
|
55
|
+
* interface and the per-backend `CapabilityDescriptor` (which must NOT be touched: whether a run
|
|
56
|
+
* executes off-request has no backend asymmetry to absorb — `runAgent` takes the same `ctx`
|
|
57
|
+
* in-request or off-request).
|
|
58
|
+
*
|
|
59
|
+
* - `durableWorker` — when true, the deployment runs a durable off-request worker (DBOS),
|
|
60
|
+
* so a per-request `async:true` run is enqueued onto it (202 + runId) rather than fail-closed-501.
|
|
61
|
+
* A lint rule (lint.ts) enforces it: a spec must not be deployed expecting async without it — but
|
|
62
|
+
* the LOAD-BEARING gate is the RUNTIME one (the run surface 501s if no executor is wired,
|
|
63
|
+
* regardless of this flag), so this is a declaration + a static best-effort check, defense-in-depth.
|
|
64
|
+
*/
|
|
65
|
+
export const DeploymentSpec = z
|
|
66
|
+
.object({
|
|
67
|
+
durableWorker: z.boolean().optional(),
|
|
68
|
+
})
|
|
69
|
+
.strict();
|
|
70
|
+
// ---------------------------------------------------------------------------------------
|
|
71
|
+
// stores[] — independent grammar (DB-materialized product tables)
|
|
72
|
+
// ---------------------------------------------------------------------------------------
|
|
73
|
+
/**
|
|
74
|
+
* The closed set of column types an author may declare. Small + closed so the store generator
|
|
75
|
+
* can map each to a Drizzle/Postgres type deterministically and the migration gate sees a finite
|
|
76
|
+
* vocabulary. (Authors declare BUSINESS columns only — the tenancy/GDPR columns `tenant_id`,
|
|
77
|
+
* `id`, `created_at`, `deleted_at`, `retention_days`, `region` are INJECTED by the generator,
|
|
78
|
+
* never declared here.)
|
|
79
|
+
*/
|
|
80
|
+
export const ColumnType = z.enum(['text', 'uuid', 'timestamp', 'integer', 'boolean', 'jsonb']);
|
|
81
|
+
/**
|
|
82
|
+
* A SAFE SQL/TS IDENTIFIER for a store name / column name / FK column-or-reference (TEN-1).
|
|
83
|
+
* Store/column names are interpolated VERBATIM into generated SQL (`CREATE TABLE "<name>"`)
|
|
84
|
+
* AND generated TS (`export const <camel> = pgTable('<name>', …)`) — so an unconstrained
|
|
85
|
+
* `z.string()` is an INJECTION seam (a name like `m" ); DROP …` lands in executable DDL, and the
|
|
86
|
+
* destructive scan is a closed blocklist that can never catch every form). Fail-closed at the
|
|
87
|
+
* SOURCE: a safe identifier is `[a-z_][a-z0-9_]*`, length 1..63 (the Postgres identifier limit),
|
|
88
|
+
* lowercase only (Postgres folds unquoted idents to lowercase; we keep snake_case author names and
|
|
89
|
+
* camelCase them for TS). `parseSpec` rejects a metacharacter/over-long name as `schema_violation`.
|
|
90
|
+
* The generators re-assert the SAME shape (defense-in-depth for a code-built spec bypassing parse).
|
|
91
|
+
*/
|
|
92
|
+
export const SAFE_IDENTIFIER_RE = /^[a-z_][a-z0-9_]*$/;
|
|
93
|
+
export const MAX_IDENTIFIER_LENGTH = 63;
|
|
94
|
+
export const SafeIdentifier = z
|
|
95
|
+
.string()
|
|
96
|
+
.min(1)
|
|
97
|
+
.max(MAX_IDENTIFIER_LENGTH, `identifier must be <= ${MAX_IDENTIFIER_LENGTH} chars (Postgres limit)`)
|
|
98
|
+
.regex(SAFE_IDENTIFIER_RE, 'identifier must match /^[a-z_][a-z0-9_]*$/ (lowercase letters/digits/underscore, no metacharacters)');
|
|
99
|
+
/**
|
|
100
|
+
* Re-assert the safe-identifier shape OUTSIDE Zod (the generators call this on a spec that may have
|
|
101
|
+
* been built in code, bypassing parseSpec). THROWS — never returns a malformed identifier into
|
|
102
|
+
* generated SQL/TS. Single source of the rule shared by the grammar refine above + both generators.
|
|
103
|
+
*/
|
|
104
|
+
export function assertSafeIdentifier(value, what) {
|
|
105
|
+
if (value.length === 0 ||
|
|
106
|
+
value.length > MAX_IDENTIFIER_LENGTH ||
|
|
107
|
+
!SAFE_IDENTIFIER_RE.test(value)) {
|
|
108
|
+
throw new Error(`unsafe identifier for ${what}: ${JSON.stringify(value)} — must match ` +
|
|
109
|
+
`/^[a-z_][a-z0-9_]*$/ and be <= ${MAX_IDENTIFIER_LENGTH} chars (injection guard, TEN-1)`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** One business column on a store. `nullable`/`unique` default false (the conservative shape). */
|
|
113
|
+
export const StoreColumn = z
|
|
114
|
+
.object({
|
|
115
|
+
name: SafeIdentifier,
|
|
116
|
+
type: ColumnType,
|
|
117
|
+
nullable: z.boolean().default(false),
|
|
118
|
+
unique: z.boolean().default(false),
|
|
119
|
+
/** Optional whitelist of allowed values for a text column (a stored value must be one of these). */
|
|
120
|
+
enum: z.array(z.string().min(1)).min(1).optional(),
|
|
121
|
+
})
|
|
122
|
+
.strict();
|
|
123
|
+
/**
|
|
124
|
+
* A child→parent foreign key (the throwaway has `transcripts` referencing `meetings`). The
|
|
125
|
+
* generator emits the FK + `ON DELETE` policy; the parent must be another declared store (the
|
|
126
|
+
* lint pass resolves `references`). This is a PRODUCT-to-PRODUCT FK; FK-to-core (e.g. orgs) is
|
|
127
|
+
* the injected tenancy column, not declared here.
|
|
128
|
+
*/
|
|
129
|
+
export const StoreForeignKey = z
|
|
130
|
+
.object({
|
|
131
|
+
/** The local column carrying the FK (must be a DECLARED business column — lint-resolved). */
|
|
132
|
+
column: SafeIdentifier,
|
|
133
|
+
/** The referenced store name (must be a declared store — lint-resolved). */
|
|
134
|
+
references: SafeIdentifier,
|
|
135
|
+
/** When set, the FK targets this (unique) column of the referenced store instead of its id. */
|
|
136
|
+
referencesColumn: SafeIdentifier.optional(),
|
|
137
|
+
/** ON DELETE policy; `cascade` mirrors the tenancy cascade discipline. */
|
|
138
|
+
onDelete: z.enum(['cascade', 'restrict', 'set null']).default('cascade'),
|
|
139
|
+
})
|
|
140
|
+
.strict();
|
|
141
|
+
/**
|
|
142
|
+
* A declared product store. Authors declare a name + business columns (+ optional child→parent
|
|
143
|
+
* FKs). Tenancy is NON-OPTIONAL by construction — there is no opt-out field (a non-tenant store
|
|
144
|
+
* would be the spec-level analogue of `.unscoped()`, deliberately not expressible in v1.0).
|
|
145
|
+
*/
|
|
146
|
+
export const StoreSpec = z
|
|
147
|
+
.object({
|
|
148
|
+
name: SafeIdentifier,
|
|
149
|
+
columns: z.array(StoreColumn).min(1),
|
|
150
|
+
foreignKeys: z.array(StoreForeignKey).default([]),
|
|
151
|
+
/** Opt-in soft delete: a delete marks the row deleted instead of removing it (default: hard delete). */
|
|
152
|
+
softDelete: z.boolean().optional(),
|
|
153
|
+
/** Opt-in full-text search: the store gets a generated tsvector column (over its text columns) + a
|
|
154
|
+
* GIN index, and a ranked search query surface. Default: substring (ILIKE) search only. */
|
|
155
|
+
fullTextSearch: z.boolean().optional(),
|
|
156
|
+
})
|
|
157
|
+
.strict();
|
|
158
|
+
// ---------------------------------------------------------------------------------------
|
|
159
|
+
// handlers[] — independent grammar (escape-hatch TS module references)
|
|
160
|
+
// ---------------------------------------------------------------------------------------
|
|
161
|
+
/**
|
|
162
|
+
* What a handler is wired into. A logical id maps to a TS module + export; `kind` declares the
|
|
163
|
+
* chokepoint it dispatches through (tool → dispatchTool; route → the api chokepoint; trigger →
|
|
164
|
+
* the triggers seam). The loader resolves the symbol from a path-jailed escape-hatch
|
|
165
|
+
* root — the grammar layer parses the mapping only.
|
|
166
|
+
*/
|
|
167
|
+
export const HandlerKind = z.enum(['tool', 'route', 'trigger']);
|
|
168
|
+
export const HandlerSpec = z
|
|
169
|
+
.object({
|
|
170
|
+
/** Logical id referenced by tooling/api/triggers. */
|
|
171
|
+
id: z.string().min(1),
|
|
172
|
+
/** The escape-hatch TS module path (resolved under the jailed root at load). */
|
|
173
|
+
module: z.string().min(1),
|
|
174
|
+
/** The named export within that module. */
|
|
175
|
+
export: z.string().min(1),
|
|
176
|
+
kind: HandlerKind,
|
|
177
|
+
/**
|
|
178
|
+
* Opt-in: a route handler that only READS product stores. When true, its route is gated
|
|
179
|
+
* `store:read` instead of the default `store:write`, so a read-scoped credential can reach it.
|
|
180
|
+
*/
|
|
181
|
+
readonly: z.boolean().optional(),
|
|
182
|
+
})
|
|
183
|
+
.strict();
|
|
184
|
+
// ---------------------------------------------------------------------------------------
|
|
185
|
+
// agents[] — WRAP core.AgentSpec
|
|
186
|
+
// ---------------------------------------------------------------------------------------
|
|
187
|
+
/**
|
|
188
|
+
* A declared agent. WRAPS `core.AgentSpec`:
|
|
189
|
+
* - `.omit({ input })` — `input` is the per-request RUNTIME value, never config.
|
|
190
|
+
* - `.omit({ tools })` — the neutral inline tool array is replaced by ID references into the
|
|
191
|
+
* `tooling[]` section (a config agent wires tools by id; lint resolves them).
|
|
192
|
+
* - `.extend(...)` — the wrap-layer fields the engine needs: a logical `id`, a `backend`
|
|
193
|
+
* selection, the `tools` id-reference list, and an optional `requireNativeStructuredOutput`
|
|
194
|
+
* flag so a capability violation (e.g. native structured output demanded on pi) is expressible
|
|
195
|
+
* and checked at config time (lint).
|
|
196
|
+
* - `.strict()` — fail-closed unknown-key rejection (applied last; verified to compose).
|
|
197
|
+
*
|
|
198
|
+
* Single source of truth: `name`/`instructions`/`model`/`outputSchema`/`maxTurns` come straight
|
|
199
|
+
* from the neutral type. If the neutral `AgentSpec` churns, this wrap is where the compat decision
|
|
200
|
+
* (minor vs major spec bump) is made — by design.
|
|
201
|
+
*/
|
|
202
|
+
export const AgentSpecConfig = NeutralAgentSpec.omit({ input: true, tools: true })
|
|
203
|
+
.extend({
|
|
204
|
+
/** Logical id (unique within `agents[]`). */
|
|
205
|
+
id: z.string().min(1),
|
|
206
|
+
/** Which backend runs this agent. */
|
|
207
|
+
backend: BackendId,
|
|
208
|
+
/** Tool ids referenced from the `tooling[]` section (lint-resolved). */
|
|
209
|
+
tools: z.array(z.string().min(1)).default([]),
|
|
210
|
+
/**
|
|
211
|
+
* When true, an `outputSchema` DEMANDS native structured output — rejected at config time on
|
|
212
|
+
* a backend that lacks it (pi). Threaded into core `validateSpec` by the lint pass.
|
|
213
|
+
*/
|
|
214
|
+
requireNativeStructuredOutput: z.boolean().default(false),
|
|
215
|
+
})
|
|
216
|
+
.strict();
|
|
217
|
+
// ---------------------------------------------------------------------------------------
|
|
218
|
+
// tooling[] — WRAP core.ToolSpec
|
|
219
|
+
// ---------------------------------------------------------------------------------------
|
|
220
|
+
/**
|
|
221
|
+
* A declared tool. WRAPS `core.ToolSpec` (name/description/parameters — the model-facing
|
|
222
|
+
* declaration) + the wrap-layer fields the resolver needs to build a `NeutralTool`:
|
|
223
|
+
* - `id` — logical id referenced from `agents[].tools` and unique within `tooling[]`.
|
|
224
|
+
* - `handler` — a logical handler id from the `handlers[]` section (lint-resolved).
|
|
225
|
+
* - `idempotent` — REQUIRED, NO DEFAULT. This is the reviewed replay-safety declaration the whole
|
|
226
|
+
* `dispatchTool` contract keys off (a `false` tool must never re-fire / return a cached output
|
|
227
|
+
* on replay). There is no platform-side verification of this boolean — it must be an explicit,
|
|
228
|
+
* reviewed author decision, so we give it no default.
|
|
229
|
+
* - `timeoutMs` — bounds the handler (AbortSignal in dispatchTool).
|
|
230
|
+
* - `outputSchema` — optional embedded JSON-Schema validating the handler output (Ajv-compiled
|
|
231
|
+
* at load by the lint pass). `parameters` (the input schema) is inherited from `ToolSpec`.
|
|
232
|
+
*/
|
|
233
|
+
export const ToolSpecConfig = NeutralToolSpec.extend({
|
|
234
|
+
/** Logical id (unique within `tooling[]`; referenced from `agents[].tools`). */
|
|
235
|
+
id: z.string().min(1),
|
|
236
|
+
/** A declared handler id (lint-resolved against `handlers[]`). */
|
|
237
|
+
handler: z.string().min(1),
|
|
238
|
+
/**
|
|
239
|
+
* The replay-safety declaration — REQUIRED, no default (a reviewed author decision; the whole
|
|
240
|
+
* dispatchTool replay contract keys off it).
|
|
241
|
+
*/
|
|
242
|
+
idempotent: z.boolean(),
|
|
243
|
+
/** Hard timeout for the handler (ms). */
|
|
244
|
+
timeoutMs: z.number().int().positive(),
|
|
245
|
+
/** Optional embedded JSON-Schema validating handler OUTPUT (Ajv-compiled at load). */
|
|
246
|
+
outputSchema: z.record(z.string(), z.unknown()).optional(),
|
|
247
|
+
}).strict();
|
|
248
|
+
// ---------------------------------------------------------------------------------------
|
|
249
|
+
// api[] — independent grammar (declared HTTP routes)
|
|
250
|
+
// ---------------------------------------------------------------------------------------
|
|
251
|
+
/** The HTTP method a route handles. */
|
|
252
|
+
export const HttpMethod = z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
|
|
253
|
+
/** A CRUD operation against a materialized store. */
|
|
254
|
+
export const StoreOp = z.enum(['list', 'get', 'create', 'update', 'delete']);
|
|
255
|
+
/**
|
|
256
|
+
* A `stream` route's runtime mode — discriminates the init shape the interpreter builds WITHIN the
|
|
257
|
+
* `kind:'stream'` arm (NOT a union discriminant — the union still discriminates on `kind`):
|
|
258
|
+
* - `ingest` — the binary write half: the interpreter reads the RAW request body.
|
|
259
|
+
* - `playback` — the media read half: Range/206 + conditional-GET from a `BlobStore`.
|
|
260
|
+
*
|
|
261
|
+
* `mode` is a per-arm field (like a store action's `op`), not a fourth `kind`: an ingest and a
|
|
262
|
+
* playback route are the SAME kind of action (a raw-Request/Response stream handler) differing only
|
|
263
|
+
* in runtime behavior, so one `kind` keeps the closed union minimal.
|
|
264
|
+
*/
|
|
265
|
+
export const StreamMode = z.enum(['ingest', 'playback']);
|
|
266
|
+
/**
|
|
267
|
+
* A route action — a discriminated union over its `kind`:
|
|
268
|
+
* - `store` — CRUD over a materialized store via TenantDb.
|
|
269
|
+
* - `agent` — invoke a declared agent over the SSE/JSON run surface.
|
|
270
|
+
* - `handler` — a declared route-handler id.
|
|
271
|
+
* - `stream` — a raw binary ingest / Range-206 playback handler; `mode`
|
|
272
|
+
* discriminates ingest vs playback WITHIN this arm (the union still keys on `kind`).
|
|
273
|
+
*
|
|
274
|
+
* The discriminant `kind` is an explicit field (not inferred from which payload is set) so the union
|
|
275
|
+
* is unambiguous and fail-closed. The `stream` arm's `handler` resolves against a declared
|
|
276
|
+
* `route`-kind handler — the SAME chokepoint a `kind:'handler'` route uses (a stream handler is a
|
|
277
|
+
* route handler that receives a raw `Request` instead of parsed JSON; the raw-vs-JSON init shape is
|
|
278
|
+
* a RUNTIME concern, not a grammar-kind concern — so no new `HandlerKind` is introduced).
|
|
279
|
+
*/
|
|
280
|
+
export const RouteAction = z.discriminatedUnion('kind', [
|
|
281
|
+
z
|
|
282
|
+
.object({
|
|
283
|
+
kind: z.literal('store'),
|
|
284
|
+
/** The declared store name (lint-resolved). */
|
|
285
|
+
store: z.string().min(1),
|
|
286
|
+
op: StoreOp,
|
|
287
|
+
})
|
|
288
|
+
.strict(),
|
|
289
|
+
z
|
|
290
|
+
.object({
|
|
291
|
+
kind: z.literal('agent'),
|
|
292
|
+
/** The declared agent id (lint-resolved). */
|
|
293
|
+
agent: z.string().min(1),
|
|
294
|
+
/**
|
|
295
|
+
* Optional: a declared store name (lint-resolved). When set, the agent's validated
|
|
296
|
+
* `outputSchema` output is written as one row into this store after a successful run —
|
|
297
|
+
* exactly-once across the sync and durable execution paths. Omitted ⇒ the run's output is
|
|
298
|
+
* returned/journaled but not persisted to a store.
|
|
299
|
+
*/
|
|
300
|
+
persistTo: z.string().min(1).optional(),
|
|
301
|
+
})
|
|
302
|
+
.strict(),
|
|
303
|
+
z
|
|
304
|
+
.object({
|
|
305
|
+
kind: z.literal('handler'),
|
|
306
|
+
/** The declared handler id (lint-resolved; must be a `route`-kind handler). */
|
|
307
|
+
handler: z.string().min(1),
|
|
308
|
+
})
|
|
309
|
+
.strict(),
|
|
310
|
+
z
|
|
311
|
+
.object({
|
|
312
|
+
kind: z.literal('stream'),
|
|
313
|
+
/**
|
|
314
|
+
* The declared handler id (lint-resolved; must be a `route`-kind handler — a stream handler
|
|
315
|
+
* dispatches through the api chokepoint, like a `kind:'handler'` route).
|
|
316
|
+
*/
|
|
317
|
+
handler: z.string().min(1),
|
|
318
|
+
/** ingest (raw binary write) vs playback (Range/206 media read) — see `StreamMode`. */
|
|
319
|
+
mode: StreamMode,
|
|
320
|
+
})
|
|
321
|
+
.strict(),
|
|
322
|
+
]);
|
|
323
|
+
/** A declared HTTP route mounted on the existing auth chain. */
|
|
324
|
+
export const ApiRouteSpec = z
|
|
325
|
+
.object({
|
|
326
|
+
method: HttpMethod,
|
|
327
|
+
/** Route path (e.g. `/meetings/{id}`); interpreted by the api interpreter. */
|
|
328
|
+
path: z.string().min(1),
|
|
329
|
+
action: RouteAction,
|
|
330
|
+
})
|
|
331
|
+
.strict();
|
|
332
|
+
// ---------------------------------------------------------------------------------------
|
|
333
|
+
// triggers[] — independent grammar (parse/register only)
|
|
334
|
+
// ---------------------------------------------------------------------------------------
|
|
335
|
+
/**
|
|
336
|
+
* A trigger action — what fires when the trigger runs. A trigger fires an agent or a declared
|
|
337
|
+
* trigger-handler (lint-resolved). Parse/register only (the durable worker is a deployment
|
|
338
|
+
* property); a cron/async fire is fail-closed-rejected at runtime (not in this grammar).
|
|
339
|
+
*/
|
|
340
|
+
export const TriggerAction = z.discriminatedUnion('kind', [
|
|
341
|
+
z
|
|
342
|
+
.object({
|
|
343
|
+
kind: z.literal('agent'),
|
|
344
|
+
agent: z.string().min(1),
|
|
345
|
+
/**
|
|
346
|
+
* Optional: a declared store name (lint-resolved). When set, the agent's validated
|
|
347
|
+
* `outputSchema` output is written as one row into this store after a successful run —
|
|
348
|
+
* exactly-once across a durable recovery re-dispatch of the same run.
|
|
349
|
+
*/
|
|
350
|
+
persistTo: z.string().min(1).optional(),
|
|
351
|
+
})
|
|
352
|
+
.strict(),
|
|
353
|
+
z.object({ kind: z.literal('handler'), handler: z.string().min(1) }).strict(),
|
|
354
|
+
]);
|
|
355
|
+
/**
|
|
356
|
+
* A declared trigger. `kind` selects the descriptor:
|
|
357
|
+
* - `cron` — requires `schedule` (a cron expression; not evaluated at the grammar level).
|
|
358
|
+
* - `webhook` — an inbound webhook (path interpreted later).
|
|
359
|
+
* - `event` — requires `event` (a logical event name).
|
|
360
|
+
* - `manual` — fired by an explicit call.
|
|
361
|
+
*
|
|
362
|
+
* `schedule`/`event` are optional at the GRAMMAR level (different kinds need different fields);
|
|
363
|
+
* the lint pass enforces the kind→field requirement (cron needs schedule, event needs event) so a
|
|
364
|
+
* malformed trigger fails fail-closed rather than parsing into a half-specified descriptor.
|
|
365
|
+
*/
|
|
366
|
+
export const TriggerKind = z.enum(['cron', 'webhook', 'event', 'manual']);
|
|
367
|
+
export const TriggerSpec = z
|
|
368
|
+
.object({
|
|
369
|
+
name: z.string().min(1),
|
|
370
|
+
kind: TriggerKind,
|
|
371
|
+
/** Cron expression — REQUIRED for `kind:'cron'` (lint-enforced). */
|
|
372
|
+
schedule: z.string().min(1).optional(),
|
|
373
|
+
/** Logical event name — REQUIRED for `kind:'event'` (lint-enforced). */
|
|
374
|
+
event: z.string().min(1).optional(),
|
|
375
|
+
/** Opt-in cron CATCH-UP: on startup, replay every interval missed while the worker was down
|
|
376
|
+
* (bounded look-back). Valid ONLY for `kind:'cron'` (lint-enforced). Default: no catch-up. */
|
|
377
|
+
catchUp: z.boolean().optional(),
|
|
378
|
+
action: TriggerAction,
|
|
379
|
+
})
|
|
380
|
+
.strict();
|
|
381
|
+
// ---------------------------------------------------------------------------------------
|
|
382
|
+
// extensions[] — independent grammar (extension-pack references)
|
|
383
|
+
// ---------------------------------------------------------------------------------------
|
|
384
|
+
/**
|
|
385
|
+
* An EXACT semantic version pin ("zero caret/tilde"). An extension
|
|
386
|
+
* pack is product code authored + versioned in its OWN repo and named by reference here, so its
|
|
387
|
+
* version MUST be pinned exactly — any range/wildcard/floating/partial form would let the resolved
|
|
388
|
+
* pack drift silently between deploys, defeating the reviewed-deploy discipline.
|
|
389
|
+
*
|
|
390
|
+
* ALLOWLIST by construction (NOT a blocklist of range characters — a blocklist false-accepts forms
|
|
391
|
+
* it doesn't enumerate, e.g. uppercase-X wildcards or floating dist-tags, AND false-rejects legit
|
|
392
|
+
* exact pins whose prerelease/build metadata contains an `x`). We accept ONLY a strict-exact semver:
|
|
393
|
+
* `MAJOR.MINOR.PATCH` (each numeric, no leading zeros) with an OPTIONAL `-prerelease` and/or
|
|
394
|
+
* `+build` metadata segment (the canonical semver.org grammar, anchored). Everything else — every
|
|
395
|
+
* range (`^`/`~`/`>=`/`<`/`=`), wildcard (`*`/`1.2.x`/`1.X`/`X`), floating dist-tag
|
|
396
|
+
* (`latest`/`stable`/`beta`/`next`), partial version (`1`/`1.2`), set/hyphen range
|
|
397
|
+
* (`1.0.0 || 2.0.0` / `1.0.0 - 2.0.0`), `v`-prefix, leading zero, or surrounding whitespace — fails
|
|
398
|
+
* by NOT matching the allowlist, so no enumeration can leak a form.
|
|
399
|
+
*
|
|
400
|
+
* Accepted: `1.2.3`, `1.2.3-rc.1`, `1.0.0-linux.1`, `2.0.0+exp.sha`, `10.20.30` (exact prerelease/
|
|
401
|
+
* build metadata — including the letter `x` inside it — is still an exact pin). We do NOT resolve
|
|
402
|
+
* the pack here (its own loader resolves + validates the actual published version); this is the
|
|
403
|
+
* fail-closed "is it EXACTLY one version?" guard at the grammar boundary.
|
|
404
|
+
*
|
|
405
|
+
* Implemented as `.regex()` (NOT `.refine()`): a `.regex()` serializes into the exported JSON-Schema
|
|
406
|
+
* as a `pattern`, so the artifact (export.ts) ALSO enforces the exact-pin constraint — a `.refine()`
|
|
407
|
+
* is dropped by `z.toJSONSchema`, which would leave the exported schema with NO version constraint.
|
|
408
|
+
*/
|
|
409
|
+
const EXACT_SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/;
|
|
410
|
+
export const ExactVersionPin = z
|
|
411
|
+
.string()
|
|
412
|
+
.min(1)
|
|
413
|
+
.regex(EXACT_SEMVER_RE, {
|
|
414
|
+
message: 'extension version must be an EXACT semver pin (MAJOR.MINOR.PATCH with optional -prerelease/' +
|
|
415
|
+
'+build) — ranges, wildcards (incl. uppercase X), floating dist-tags (latest/beta/…), and ' +
|
|
416
|
+
'partial versions (1, 1.2) are rejected',
|
|
417
|
+
});
|
|
418
|
+
/**
|
|
419
|
+
* A reference to an extension pack to load. The pack carries ALL product code (its
|
|
420
|
+
* own stores/handlers/tooling/route fragments + capability impls); core validates ONLY this
|
|
421
|
+
* reference shape, never the pack's contents. `config` is an OPEN passthrough record whose CONTENTS
|
|
422
|
+
* are validated by the PACK's own Zod at load time, NEVER by core — but the ExtensionRef
|
|
423
|
+
* wrapper itself is `.strict()`, so an unknown key ON THE REF is fail-closed-rejected.
|
|
424
|
+
*
|
|
425
|
+
* - `id` — a logical id for the pack (unique within `extensions[]`; lint-resolvable later).
|
|
426
|
+
* - `module` — the pack module/directory reference (resolved + path-jailed by `loadExtensions`).
|
|
427
|
+
* - `version` — an EXACT version pin (no range — see `ExactVersionPin`).
|
|
428
|
+
* - `config` — optional opaque pack-validated config (passthrough; core does not inspect it).
|
|
429
|
+
*/
|
|
430
|
+
export const ExtensionRef = z
|
|
431
|
+
.object({
|
|
432
|
+
id: z.string().min(1),
|
|
433
|
+
module: z.string().min(1),
|
|
434
|
+
version: ExactVersionPin,
|
|
435
|
+
config: z.record(z.string(), z.unknown()).optional(),
|
|
436
|
+
})
|
|
437
|
+
.strict();
|
|
438
|
+
// ---------------------------------------------------------------------------------------
|
|
439
|
+
// frontend[] — independent grammar (static frontend mounts served alongside the API)
|
|
440
|
+
// ---------------------------------------------------------------------------------------
|
|
441
|
+
/**
|
|
442
|
+
* One static frontend mount served alongside the backend's API. A backend may declare a list of
|
|
443
|
+
* these so a spec can ship its own web UI (built assets) next to the routes it exposes.
|
|
444
|
+
*
|
|
445
|
+
* - `route` — the URL prefix the mount is served under (e.g. `/` or `/app`); must start with `/`.
|
|
446
|
+
* - `dir` — the directory of built static assets, relative to the spec file.
|
|
447
|
+
* - `spa` — when true, an unmatched path under `route` falls back to `index.html` (the
|
|
448
|
+
* History-API single-page-app fallback); default false (plain static file serving).
|
|
449
|
+
*
|
|
450
|
+
* `.strict()` — fail-closed unknown-key rejection, consistent with every other grammar level.
|
|
451
|
+
*/
|
|
452
|
+
export const FrontendSpec = z
|
|
453
|
+
.object({
|
|
454
|
+
route: z.string().min(1).regex(/^\//, 'route must start with "/"'),
|
|
455
|
+
dir: z.string().min(1),
|
|
456
|
+
spa: z.boolean().default(false),
|
|
457
|
+
})
|
|
458
|
+
.strict();
|
|
459
|
+
// ---------------------------------------------------------------------------------------
|
|
460
|
+
// RaySpec — the whole document
|
|
461
|
+
// ---------------------------------------------------------------------------------------
|
|
462
|
+
/**
|
|
463
|
+
* The full RaySpec config document. `version` is `z.literal('1.0')` — but the parser checks it
|
|
464
|
+
* FIRST (two-phase, see `parse.ts`) so an unsupported major yields a clean `unsupported_version`
|
|
465
|
+
* SpecError instead of a wall of strict-shape errors. `.strict()` at the top level rejects any
|
|
466
|
+
* unknown top-level section.
|
|
467
|
+
*
|
|
468
|
+
* Every section defaults to `[]` so a minimal spec (just `version` + `metadata`) is valid.
|
|
469
|
+
*/
|
|
470
|
+
export const RaySpec = z
|
|
471
|
+
.object({
|
|
472
|
+
version: z.literal(SPEC_VERSION),
|
|
473
|
+
metadata: Metadata,
|
|
474
|
+
stores: z.array(StoreSpec).default([]),
|
|
475
|
+
api: z.array(ApiRouteSpec).default([]),
|
|
476
|
+
agents: z.array(AgentSpecConfig).default([]),
|
|
477
|
+
tooling: z.array(ToolSpecConfig).default([]),
|
|
478
|
+
triggers: z.array(TriggerSpec).default([]),
|
|
479
|
+
handlers: z.array(HandlerSpec).default([]),
|
|
480
|
+
/**
|
|
481
|
+
* OPTIONAL extension-pack references. Defaults to `[]` so a minimal spec (just
|
|
482
|
+
* `version` + `metadata`) and every existing fixture stays valid — absent = NO-OP (no packs
|
|
483
|
+
* loaded). Each entry's contents (`config`) are validated by the pack itself, never core;
|
|
484
|
+
* the ref wrapper is `.strict()` (fail-closed on an unknown key). The `loadExtensions` merge
|
|
485
|
+
* threads pack fragments into the other sections.
|
|
486
|
+
*/
|
|
487
|
+
extensions: z.array(ExtensionRef).default([]),
|
|
488
|
+
/**
|
|
489
|
+
* OPTIONAL deployment properties. An object (not an array) — absent ⇒ no
|
|
490
|
+
* durable worker (the default; a per-request `async:true` then fail-closed-501s at the run
|
|
491
|
+
* surface). A minimal spec (just `version` + `metadata`) stays valid (deployment is omittable).
|
|
492
|
+
*/
|
|
493
|
+
deployment: DeploymentSpec.optional(),
|
|
494
|
+
/**
|
|
495
|
+
* OPTIONAL static frontend mounts. A list of `{route, dir, spa?}` entries served alongside the
|
|
496
|
+
* API (see `FrontendSpec`). `.optional()` (NOT `.default([])`) so a spec that omits `frontend`
|
|
497
|
+
* parses byte-identically — absent = NO static mounts. A minimal spec (just `version` +
|
|
498
|
+
* `metadata`) stays valid (frontend is omittable).
|
|
499
|
+
*/
|
|
500
|
+
frontend: z.array(FrontendSpec).optional(),
|
|
501
|
+
})
|
|
502
|
+
.strict();
|
|
503
|
+
//# sourceMappingURL=grammar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar.js","sourceRoot":"","sources":["../src/grammar.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rayspec/spec — the RaySpec config grammar, parser, linter, and JSON-Schema exporter.
|
|
3
|
+
*
|
|
4
|
+
* A deployed RaySpec backend is ONE validated `RaySpec` (stores · api · agents ·
|
|
5
|
+
* tooling · triggers · handlers). This package owns the GRAMMAR + the fail-closed validation
|
|
6
|
+
* pipeline; the interpreters that turn a validated spec into running infrastructure are built in
|
|
7
|
+
* the interpreter packages (and depend on this package).
|
|
8
|
+
*/
|
|
9
|
+
export * from './brace-params.js';
|
|
10
|
+
export * from './detect.js';
|
|
11
|
+
export * from './errors.js';
|
|
12
|
+
export * from './export.js';
|
|
13
|
+
export * from './grammar.js';
|
|
14
|
+
export * from './lint.js';
|
|
15
|
+
export * from './parse.js';
|
|
16
|
+
export * from './product-events.js';
|
|
17
|
+
export * from './product-grammar.js';
|
|
18
|
+
export * from './product-lint.js';
|
|
19
|
+
export * from './product-parse.js';
|
|
20
|
+
export * from './product-scope.js';
|
|
21
|
+
export * from './product-views.js';
|
|
22
|
+
export * from './product-views-lint.js';
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @rayspec/spec — the RaySpec config grammar, parser, linter, and JSON-Schema exporter.
|
|
3
|
+
*
|
|
4
|
+
* A deployed RaySpec backend is ONE validated `RaySpec` (stores · api · agents ·
|
|
5
|
+
* tooling · triggers · handlers). This package owns the GRAMMAR + the fail-closed validation
|
|
6
|
+
* pipeline; the interpreters that turn a validated spec into running infrastructure are built in
|
|
7
|
+
* the interpreter packages (and depend on this package).
|
|
8
|
+
*/
|
|
9
|
+
// Product-YAML family: the Product-YAML program document grammar/parser/linter + the
|
|
10
|
+
// dispatch layer that routes a raw spec to the right family. Additive — the RaySpec surface above
|
|
11
|
+
// is unchanged.
|
|
12
|
+
export * from './brace-params.js';
|
|
13
|
+
export * from './detect.js';
|
|
14
|
+
export * from './errors.js';
|
|
15
|
+
export * from './export.js';
|
|
16
|
+
export * from './grammar.js';
|
|
17
|
+
export * from './lint.js';
|
|
18
|
+
export * from './parse.js';
|
|
19
|
+
export * from './product-events.js';
|
|
20
|
+
export * from './product-grammar.js';
|
|
21
|
+
export * from './product-lint.js';
|
|
22
|
+
export * from './product-parse.js';
|
|
23
|
+
export * from './product-scope.js';
|
|
24
|
+
export * from './product-views.js';
|
|
25
|
+
export * from './product-views-lint.js';
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,qFAAqF;AACrF,kGAAkG;AAClG,gBAAgB;AAChB,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC"}
|