@cleocode/lafs-protocol 0.1.1 → 1.0.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/lafs.md CHANGED
@@ -2,19 +2,41 @@
2
2
 
3
3
  ## 1. Scope
4
4
 
5
- LAFS defines a protocol for software systems whose primary consumer is an LLM agent.
5
+ LAFS is a **response envelope contract specification**. It defines the canonical shape of structured responses — success envelopes, error envelopes, pagination metadata, and context preservation — for software systems whose primary consumer is an LLM agent or AI-driven tool.
6
6
 
7
- LAFS is transport-agnostic and language-agnostic. It applies to CLI, SDK, HTTP, gRPC, and orchestrated multi-agent systems.
7
+ LAFS is **not** a protocol, framework, or runtime. It specifies **what** a conformant response looks like, not how that response is transported or generated. Implementations MAY deliver LAFS envelopes over HTTP, gRPC, CLI, SDK interfaces, message queues, or any other transport mechanism. LAFS is transport-agnostic and language-agnostic.
8
+
9
+ LAFS is designed to complement — not compete with — existing agent and tool-integration protocols. The Model Context Protocol (MCP) defines how LLM hosts discover and invoke tools; the Agent-to-Agent protocol (A2A) defines how autonomous agents communicate and delegate tasks. LAFS operates at a different layer: it standardizes the **response contract** that tools and agents SHOULD return, regardless of the protocol used to invoke them. An MCP tool server, an A2A agent, or a plain REST API MAY all return LAFS-conformant envelopes.
10
+
11
+ While LAFS is purpose-built for AI and LLM tool ecosystems — where deterministic, machine-parseable responses are critical — the specification is generally applicable to any API that benefits from structured, predictable response contracts.
12
+
13
+ ---
14
+
15
+ ## 2. Non-Goals
16
+
17
+ The following capabilities are intentionally outside the scope of LAFS. This section exists to prevent scope creep and to clarify boundaries with complementary protocols.
18
+
19
+ 1. **Streaming responses.** LAFS defines discrete request/response envelopes. Streaming mechanisms such as SSE or WebSocket are transport concerns and MUST NOT be defined by LAFS.
20
+
21
+ 2. **Asynchronous processing.** LAFS envelopes are synchronous response contracts. Async job patterns (polling, webhooks, callback queues) are application-layer concerns and are outside LAFS scope.
22
+
23
+ 3. **Authentication and authorization.** LAFS is transport-agnostic; auth is a transport or middleware concern. LAFS MAY carry auth-related error codes (e.g., `E_AUTH_*`) but MUST NOT define authentication or authorization flows.
24
+
25
+ 4. **Multi-modal content.** LAFS envelopes carry structured JSON data. Binary payloads, media content negotiation, and multi-modal encoding are outside scope.
26
+
27
+ 5. **Transport binding.** LAFS defines the response envelope shape, not how it maps to HTTP status codes, gRPC metadata, or other transport semantics. Transport mapping specifications are a separate concern.
28
+
29
+ 6. **Service discovery.** LAFS does not define how consumers locate or enumerate LAFS-conformant endpoints. Discovery mechanisms SHOULD be provided by the deployment layer or complementary protocols.
8
30
 
9
31
  ---
10
32
 
11
- ## 2. RFC 2119 Keywords
33
+ ## 3. RFC 2119 Keywords
12
34
 
13
35
  The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are interpreted per RFC 2119.
14
36
 
15
37
  ---
16
38
 
17
- ## 3. Non-Negotiable Protocol Rules
39
+ ## 4. Non-Negotiable Protocol Rules
18
40
 
19
41
  1. Output default MUST be machine-readable JSON.
20
42
  2. Human-readable mode MUST be explicit opt-in.
@@ -25,9 +47,9 @@ The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are interpreted per RFC
25
47
 
26
48
  ---
27
49
 
28
- ## 4. Format Semantics
50
+ ## 5. Format Semantics
29
51
 
30
- ### 4.1 Required output semantics
52
+ ### 5.1 Required output semantics
31
53
 
32
54
  - Default format MUST be `json`.
33
55
  - `--human` MUST switch output mode to human-readable.
@@ -35,7 +57,7 @@ The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are interpreted per RFC
35
57
  - Providing both `--human` and `--json` MUST fail with `E_FORMAT_CONFLICT`.
36
58
  - Explicit flags MUST override env/config defaults.
37
59
 
38
- ### 4.2 Recommended precedence
60
+ ### 5.2 Recommended precedence
39
61
 
40
62
  1. Explicit CLI/API request value
41
63
  2. Project config
@@ -44,7 +66,7 @@ The keywords MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are interpreted per RFC
44
66
 
45
67
  ---
46
68
 
47
- ## 5. Canonical Response Envelope
69
+ ## 6. Canonical Response Envelope
48
70
 
49
71
  All responses MUST conform to `schemas/v1/envelope.schema.json`.
50
72
 
@@ -69,16 +91,25 @@ All responses MUST conform to `schemas/v1/envelope.schema.json`.
69
91
  }
70
92
  ```
71
93
 
72
- ### 5.1 Envelope invariants
94
+ ### 6.1 Envelope invariants
73
95
 
74
96
  - Exactly one of `result` or `error` MUST be non-null.
75
- - `success=true` implies `error=null`.
76
- - `success=false` implies `result=null`.
97
+ - `success=true` implies `error=null` or error omitted.
98
+ - `success=false` implies `result=null` and `error` MUST be present.
99
+ - The `page` and `error` fields are optional when their value would be null. In strict mode, producers SHOULD omit these fields rather than set them to null.
77
100
  - Unknown fields SHOULD be rejected when strict mode is enabled.
78
101
 
102
+ ### 6.2 Extensions
103
+
104
+ The envelope supports an optional `_extensions` object for vendor-specific metadata. Because `_extensions` is a declared property in the schema, it is permitted regardless of strict mode.
105
+
106
+ - Keys SHOULD use the `x-` prefix convention (e.g., `x-myvendor-trace-id`).
107
+ - Consumers MUST NOT rely on extension fields for protocol-required behavior.
108
+ - Producers MAY omit `_extensions` entirely; the field is always optional.
109
+
79
110
  ---
80
111
 
81
- ## 6. Error Contract
112
+ ## 7. Error Contract
82
113
 
83
114
  Errors MUST conform to envelope `error` shape and use codes from `schemas/v1/error-registry.json`.
84
115
 
@@ -95,7 +126,30 @@ Errors MUST conform to envelope `error` shape and use codes from `schemas/v1/err
95
126
  }
96
127
  ```
97
128
 
98
- ### 6.1 Required behavior
129
+ ### 7.1 Error code naming convention
130
+
131
+ Error codes MUST match the pattern: `^E_[A-Z0-9]+_[A-Z0-9_]+$`
132
+
133
+ The structure is **E\_\<DOMAIN\>\_\<SPECIFIC\>**, where:
134
+
135
+ - **E\_** — required prefix identifying the value as an error code.
136
+ - **DOMAIN** — a short uppercase token describing the error's semantic area (e.g., `VALIDATION`, `CONTEXT`, `RATE`, `MIGRATION`). The domain is descriptive; it does not need to equal the `category` enum value.
137
+ - **SPECIFIC** — one or more uppercase tokens (separated by `_`) that distinguish the error within its domain (e.g., `SCHEMA`, `MISSING`, `UNSUPPORTED_VERSION`).
138
+
139
+ Examples from the registry:
140
+
141
+ | Code | Domain | Specific | Category |
142
+ |---|---|---|---|
143
+ | `E_VALIDATION_SCHEMA` | `VALIDATION` | `SCHEMA` | VALIDATION |
144
+ | `E_NOT_FOUND_RESOURCE` | `NOT` | `FOUND_RESOURCE` | NOT_FOUND |
145
+ | `E_CONTEXT_MISSING` | `CONTEXT` | `MISSING` | CONTRACT |
146
+ | `E_MIGRATION_UNSUPPORTED_VERSION` | `MIGRATION` | `UNSUPPORTED_VERSION` | MIGRATION |
147
+
148
+ Registered categories (the `category` field in error objects): `VALIDATION`, `AUTH`, `PERMISSION`, `NOT_FOUND`, `CONFLICT`, `RATE_LIMIT`, `TRANSIENT`, `INTERNAL`, `CONTRACT`, `MIGRATION`.
149
+
150
+ Custom error codes MUST match the same regex pattern. Implementations SHOULD choose a domain token that clearly communicates the error's origin.
151
+
152
+ ### 7.2 Required behavior
99
153
 
100
154
  - Error codes MUST be stable within major versions.
101
155
  - Retry semantics MUST be encoded in `retryable` and `retryAfterMs`.
@@ -103,7 +157,7 @@ Errors MUST conform to envelope `error` shape and use codes from `schemas/v1/err
103
157
 
104
158
  ---
105
159
 
106
- ## 7. Context Preservation
160
+ ## 8. Context Preservation
107
161
 
108
162
  Multi-step operations MUST preserve a context ledger with at least:
109
163
 
@@ -122,30 +176,209 @@ Rules:
122
176
  - Decisions affecting output MUST be represented in ledger state.
123
177
  - Missing required context for a mutating step MUST fail with structured error.
124
178
 
179
+ ### 8.1 Context Retrieval
180
+
181
+ Agents MAY retrieve context ledger state via `GET /_lafs/context/{ledgerId}` with projection modes.
182
+
183
+ #### 8.1.1 Projection Modes
184
+
185
+ **Full Mode (`mode=full`):**
186
+ Returns complete ledger including all entries.
187
+ - Use for: Initial loads, recovery scenarios
188
+ - Supports: Offset-based pagination
189
+ - Response includes: All ledger fields
190
+
191
+ **Delta Mode (`mode=delta&sinceVersion=N`):**
192
+ Returns only entries added since version N.
193
+ - Use for: Active workflows (efficient sync)
194
+ - Response includes:
195
+ ```json
196
+ {
197
+ "ledgerId": "ctx_abc123",
198
+ "mode": "delta",
199
+ "fromVersion": 10,
200
+ "toVersion": 15,
201
+ "entries": [/* new entries only */],
202
+ "removedConstraints": [/* constraints no longer active */],
203
+ "checksum": "sha256:..."
204
+ }
205
+ ```
206
+
207
+ **Summary Mode (`mode=summary`):**
208
+ Returns checksum and version for validation.
209
+ - Use for: Quick sync validation
210
+ - Response includes only: `ledgerId`, `version`, `checksum`, `entryCount`
211
+
212
+ #### 8.1.2 Query Parameters
213
+
214
+ | Parameter | Type | Description |
215
+ |-----------|------|-------------|
216
+ | `mode` | enum | `full`, `delta`, `summary` |
217
+ | `sinceVersion` | integer | For delta mode: return entries after this version |
218
+ | `filterByOperation` | string[] | Filter entries by operation name(s) |
219
+ | `limit` | integer | Max entries (1-1000, default 100) |
220
+ | `includeChecksum` | boolean | Include integrity checksum (default true) |
221
+
222
+ #### 8.1.3 Agent Guidance
223
+
224
+ - **Initial load**: Use `mode=full` once
225
+ - **Active workflows**: Use `mode=delta` with last known version
226
+ - **Validation**: Use `mode=summary` to verify sync state
227
+ - **Default recommendation**: `delta` mode for agent-optimal behavior
228
+
125
229
  ---
126
230
 
127
- ## 8. MVI and Progressive Disclosure
231
+ ## 9. MVI and Progressive Disclosure
128
232
 
129
- ### 8.1 MVI default
233
+ ### 9.1 MVI default
130
234
 
131
235
  - Default list/batch outputs MUST only contain fields required for next action.
132
236
  - Verbose fields SHOULD be omitted by default.
133
237
  - Systems SHOULD publish operation-level MVI budgets.
134
238
 
135
- ### 8.2 Progressive disclosure
239
+ ### 9.2 Field selection (`_fields`)
240
+
241
+ Clients MAY request a subset of response fields via the `_fields` request parameter.
242
+
243
+ - `_fields` MUST be an array of strings identifying top-level result field names.
244
+ - When `_fields` is present, the server MUST return only the requested fields plus any MVI-required fields for the declared disclosure level.
245
+ - When `_fields` is absent, the server MUST return fields appropriate for the declared `_meta.mvi` disclosure level.
246
+ - If a requested field does not exist on the resource, the server SHOULD omit it silently (no error). Servers MAY include a warning in `_meta.warnings` for unknown fields.
247
+ - `_fields` MUST NOT affect envelope structural fields (`$schema`, `_meta`, `success`, `error`, `page`, `_extensions`); it applies only to the contents of `result`.
136
248
 
137
- - Expanded detail retrieval MUST require explicit request.
138
- - Unknown expansion fields SHOULD fail validation.
249
+ ### 9.3 Expansion mechanism (`_expand`)
139
250
 
140
- ### 8.3 Pagination
251
+ Clients MAY request expanded/nested data via the `_expand` request parameter.
252
+
253
+ - `_expand` MUST be an array of strings identifying relationships or nested resources to include inline.
254
+ - When `_expand` is present, the server MUST resolve and inline the requested expansions within `result`.
255
+ - If a requested expansion field is not recognized, the server MUST return error code `E_DISCLOSURE_UNKNOWN_FIELD` with category `VALIDATION`.
256
+ - Servers SHOULD document available expansion fields per operation.
257
+ - Expansion depth MUST be limited to prevent unbounded recursion. Servers SHOULD enforce a maximum expansion depth and return `E_MVI_BUDGET_EXCEEDED` if exceeded.
258
+
259
+ ### 9.4 Pagination
141
260
 
142
261
  - List operations SHOULD return deterministic `page` metadata.
143
262
  - Pagination mode (offset or cursor) MUST be documented.
144
263
  - Mixed pagination modes in one request MUST fail validation.
145
264
 
265
+ ### 9.5 Token Budget Signaling
266
+
267
+ Token budget signaling enables clients to declare resource constraints that servers MUST respect when generating responses. This mechanism prevents context window overflow in LLM-driven workflows.
268
+
269
+ #### 9.5.1 Budget Declaration (`_budget`)
270
+
271
+ Clients MAY declare resource constraints via the `_budget` request parameter:
272
+
273
+ ```json
274
+ {
275
+ "_budget": {
276
+ "maxTokens": 4000,
277
+ "maxBytes": 32768,
278
+ "maxItems": 100
279
+ }
280
+ }
281
+ ```
282
+
283
+ **Fields:**
284
+ - `maxTokens` (integer) - Maximum approximate tokens
285
+ - `maxBytes` (integer) - Maximum byte size
286
+ - `maxItems` (integer) - Maximum items in lists
287
+
288
+ **Constraints:**
289
+ - At least one field MUST be present
290
+ - All values MUST be positive integers
291
+ - Servers MAY reject budgets exceeding implementation limits
292
+
293
+ #### 9.5.2 Server Behavior
294
+
295
+ Servers MUST:
296
+ 1. Parse `_budget` from incoming requests
297
+ 2. Estimate/measure response size
298
+ 3. Return response within budget OR fail with `E_MVI_BUDGET_EXCEEDED`
299
+
300
+ Servers MAY truncate responses using:
301
+ - **Depth-first**: Remove deepest nested fields
302
+ - **Field priority**: Remove non-essential fields first
303
+ - **Hybrid**: Combine both strategies
304
+
305
+ When truncation occurs, servers MUST include:
306
+ ```json
307
+ {
308
+ "_meta": {
309
+ "warnings": [{
310
+ "code": "E_MVI_BUDGET_TRUNCATED",
311
+ "message": "Response truncated to fit token budget"
312
+ }],
313
+ "_tokenEstimate": {
314
+ "estimated": 2847,
315
+ "budget": 4000,
316
+ "method": "character_based"
317
+ }
318
+ }
319
+ }
320
+ ```
321
+
322
+ #### 9.5.3 Error Specification
323
+
324
+ **E_MVI_BUDGET_EXCEEDED:**
325
+ - **Category:** `VALIDATION`
326
+ - **Retryable:** `true`
327
+ - **Details:** `estimatedTokens`, `budget`, `excessTokens`, `constraint`
328
+
329
+ ```json
330
+ {
331
+ "error": {
332
+ "code": "E_MVI_BUDGET_EXCEEDED",
333
+ "message": "Response exceeds declared token budget",
334
+ "category": "VALIDATION",
335
+ "retryable": true,
336
+ "details": {
337
+ "estimatedTokens": 5234,
338
+ "budget": 4000,
339
+ "excessTokens": 1234,
340
+ "constraint": "maxTokens"
341
+ }
342
+ }
343
+ }
344
+ ```
345
+
346
+ #### 9.5.4 Token Estimation Algorithm (Normative)
347
+
348
+ Servers MUST implement this algorithm or equivalent (within +/- 10%):
349
+
350
+ ```
351
+ FUNCTION estimate_tokens(value, depth = 0):
352
+ IF depth > 20: RETURN INFINITY
353
+ IF value IS null: RETURN 1
354
+ IF value IS boolean: RETURN 1
355
+ IF value IS number: RETURN max(1, len(stringify(value)) / 4)
356
+ IF value IS string:
357
+ graphemes = count_grapheme_clusters(value)
358
+ RETURN max(1, graphemes / 4.0)
359
+ IF value IS array:
360
+ tokens = 2 // []
361
+ FOR item IN value:
362
+ tokens += estimate_tokens(item, depth + 1) + 1
363
+ RETURN tokens
364
+ IF value IS object:
365
+ tokens = 2 // {}
366
+ FOR key, val IN value:
367
+ tokens += estimate_tokens(key, depth + 1)
368
+ tokens += 2 // : and ,
369
+ tokens += estimate_tokens(val, depth + 1)
370
+ RETURN tokens
371
+ ```
372
+
373
+ **Requirements:**
374
+ - Count grapheme clusters (not bytes) for unicode
375
+ - Enforce max depth of 20
376
+ - Handle circular references
377
+ - Complete within 10ms for 100KB payloads
378
+
146
379
  ---
147
380
 
148
- ## 9. Strictness
381
+ ## 10. Strictness
149
382
 
150
383
  - Agent surfaces SHOULD default `strict=true`.
151
384
  - Strict mode violations SHOULD fail with contract/validation error codes.
@@ -153,7 +386,7 @@ Rules:
153
386
 
154
387
  ---
155
388
 
156
- ## 10. Versioning and Deprecation
389
+ ## 11. Versioning and Deprecation
157
390
 
158
391
  - Protocol versions MUST follow SemVer.
159
392
  - Minor/patch changes MUST be backward compatible.
@@ -164,6 +397,81 @@ See `docs/VERSIONING.md` and `docs/DEPRECATION.md`.
164
397
 
165
398
  ---
166
399
 
167
- ## 11. Conformance
400
+ ## 12. Conformance
168
401
 
169
402
  Conforming implementations MUST pass minimum checks in `docs/CONFORMANCE.md` and schema validation for the canonical envelope.
403
+
404
+ ### 12.1 Adoption Tiers
405
+
406
+ LAFS defines three adoption tiers to enable gradual conformance. Each tier builds on the previous tier's requirements. Implementations MUST declare which tier they target and MUST pass all checks required by that tier.
407
+
408
+ #### 12.1.1 Core Tier
409
+
410
+ The Core tier represents **minimum viable LAFS adoption**. It verifies that responses use the canonical envelope shape and satisfy basic structural invariants.
411
+
412
+ Required conformance checks:
413
+
414
+ | Check | Description |
415
+ |---|---|
416
+ | `envelope_schema_valid` | Response validates against `schemas/v1/envelope.schema.json` |
417
+ | `envelope_invariants` | `success`/`result`/`error` mutual exclusivity holds (Section 6.1) |
418
+
419
+ Use cases: quick adoption, internal APIs, prototyping, evaluating LAFS fit.
420
+
421
+ #### 12.1.2 Standard Tier
422
+
423
+ The Standard tier is **recommended for production** use. It adds semantic checks for error codes, metadata flags, and format defaults on top of all Core tier requirements.
424
+
425
+ Required conformance checks — all Core checks, plus:
426
+
427
+ | Check | Description |
428
+ |---|---|
429
+ | `error_code_registered` | All error codes come from the registered error registry (Section 7) |
430
+ | `meta_mvi_present` | `_meta.mvi` flag is present and valid (Section 9.1) |
431
+ | `meta_strict_present` | `_meta.strict` flag is present and boolean (Section 10) |
432
+ | `json_protocol_default` | JSON is the default output format when no explicit format is requested (Section 5.1) |
433
+
434
+ Use cases: production APIs, public-facing services, third-party integrations.
435
+
436
+ #### 12.1.3 Complete Tier
437
+
438
+ The Complete tier represents **full LAFS compliance**. It adds configuration, flag-handling, and advanced feature checks on top of all Standard tier requirements.
439
+
440
+ Required conformance checks — all Standard checks, plus:
441
+
442
+ | Check | Description |
443
+ |---|---|
444
+ | `config_override_respected` | Project/user config-based format overrides are correctly applied (Section 5.2) |
445
+ | `flag_conflict_rejected` | Conflicting format flags (e.g., `--human --json`) are properly rejected with `E_FORMAT_CONFLICT` (Section 5.1) |
446
+ | `context_validation` | Context preservation invariants hold for multi-step operations (Section 8) |
447
+ | `pagination_validation` | Pagination metadata validates when present (Section 9.3) |
448
+
449
+ Use cases: official LAFS-conformant implementations, reference implementations, certification.
450
+
451
+ > **Note:** `context_validation` and `pagination_validation` are reserved check names. Implementations SHOULD treat these as automatically passing until the corresponding conformance runners are available.
452
+
453
+ ---
454
+
455
+ ## 13. Security Considerations
456
+
457
+ This section addresses security threats relevant to LAFS envelope production and consumption. LAFS is transport-agnostic and does not define its own cryptographic or authentication mechanisms; implementers MUST rely on the underlying transport and application layers for those controls.
458
+
459
+ ### 13.1 Injection attacks
460
+
461
+ LAFS envelopes carry user-provided data in `result`, `error`, and `details` fields. Implementers MUST sanitize all envelope contents before rendering in HTML, constructing shell commands, or executing in eval-like contexts. Error messages MUST NOT contain unsanitized user input. Implementations that embed envelope values in SQL, LDAP, or similar query languages MUST use parameterized interfaces.
462
+
463
+ ### 13.2 Tampering
464
+
465
+ LAFS does not define integrity protection at the envelope level. If envelope integrity is required, implementers SHOULD use transport-level security (e.g., TLS) and MAY implement envelope signing as an extension. Consumers MUST NOT trust envelope contents without verifying the transport channel. Implementations that relay envelopes across trust boundaries SHOULD re-validate against `schemas/v1/envelope.schema.json` at each boundary.
466
+
467
+ ### 13.3 Information disclosure
468
+
469
+ Error details MAY contain sensitive information such as stack traces, internal paths, or database identifiers. Implementations SHOULD distinguish between development and production error detail levels. The `details` field in error objects MUST NOT expose internal system information in production environments. Implementations SHOULD define an explicit allow-list of fields permitted in production error responses.
470
+
471
+ ### 13.4 Replay attacks
472
+
473
+ LAFS includes `requestId` and `timestamp` in `_meta` for correlation (Section 6). Implementers MAY use these fields for replay detection but MUST NOT rely solely on them, as LAFS does not mandate uniqueness or freshness guarantees for these values. Transport-level replay protection (e.g., TLS with appropriate session management) is RECOMMENDED.
474
+
475
+ ### 13.5 Denial of service
476
+
477
+ Large envelope payloads could be used for resource exhaustion. Implementations SHOULD enforce maximum envelope size limits appropriate to their deployment context. Pagination (Section 9.3) SHOULD be used to bound response sizes for list operations. Implementations SHOULD reject envelopes that exceed the configured size limit with a structured error.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cleocode/lafs-protocol",
3
- "version": "0.1.1",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "LLM-Agent-First Specification schemas and conformance tooling",
@@ -50,13 +50,18 @@
50
50
  ],
51
51
  "license": "MIT",
52
52
  "devDependencies": {
53
+ "@modelcontextprotocol/sdk": "^1.26.0",
54
+ "@types/express": "^5.0.6",
53
55
  "@types/node": "^24.3.0",
56
+ "@types/supertest": "^6.0.3",
57
+ "supertest": "^7.2.2",
54
58
  "tsx": "^4.20.5",
55
59
  "typescript": "^5.9.2",
56
60
  "vitest": "^2.1.9"
57
61
  },
58
62
  "dependencies": {
59
- "ajv": "^8.17.1",
60
- "ajv-formats": "^3.0.1"
63
+ "ajv": "^8.18.0",
64
+ "ajv-formats": "^3.0.1",
65
+ "express": "^5.2.1"
61
66
  }
62
67
  }
@@ -0,0 +1,70 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://lafs.dev/schemas/v1/context-ledger.schema.json",
4
+ "title": "LAFS Context Ledger",
5
+ "description": "Tracks state across request/response cycles for context preservation",
6
+ "type": "object",
7
+ "required": ["ledgerId", "version", "createdAt", "updatedAt", "entries", "checksum", "maxEntries"],
8
+ "properties": {
9
+ "ledgerId": {
10
+ "type": "string",
11
+ "description": "Unique identifier for this context ledger instance"
12
+ },
13
+ "version": {
14
+ "type": "integer",
15
+ "minimum": 0,
16
+ "description": "Monotonically increasing version number matching _meta.contextVersion"
17
+ },
18
+ "createdAt": {
19
+ "type": "string",
20
+ "format": "date-time",
21
+ "description": "ISO 8601 timestamp when the ledger was created"
22
+ },
23
+ "updatedAt": {
24
+ "type": "string",
25
+ "format": "date-time",
26
+ "description": "ISO 8601 timestamp of the last ledger update"
27
+ },
28
+ "entries": {
29
+ "type": "array",
30
+ "items": {
31
+ "type": "object",
32
+ "required": ["entryId", "timestamp", "operation", "contextDelta"],
33
+ "properties": {
34
+ "entryId": {
35
+ "type": "string",
36
+ "description": "Unique identifier for this ledger entry"
37
+ },
38
+ "timestamp": {
39
+ "type": "string",
40
+ "format": "date-time"
41
+ },
42
+ "operation": {
43
+ "type": "string",
44
+ "description": "The operation that generated this entry"
45
+ },
46
+ "contextDelta": {
47
+ "type": "object",
48
+ "description": "The context changes introduced by this operation",
49
+ "additionalProperties": true
50
+ },
51
+ "requestId": {
52
+ "type": "string",
53
+ "description": "Correlation with the request that produced this entry"
54
+ }
55
+ }
56
+ },
57
+ "description": "Ordered array of context entries (append-only)"
58
+ },
59
+ "checksum": {
60
+ "type": "string",
61
+ "description": "Integrity checksum of the ledger contents"
62
+ },
63
+ "maxEntries": {
64
+ "type": "integer",
65
+ "minimum": 1,
66
+ "description": "Maximum number of entries before truncation/compaction"
67
+ }
68
+ },
69
+ "additionalProperties": false
70
+ }
@@ -0,0 +1,132 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://lafs.dev/schemas/v1/discovery.schema.json",
4
+ "title": "LAFS Discovery Document",
5
+ "description": "Schema for LAFS agent discovery documents served at /.well-known/lafs.json",
6
+ "type": "object",
7
+ "required": [
8
+ "$schema",
9
+ "lafs_version",
10
+ "service",
11
+ "capabilities",
12
+ "endpoints"
13
+ ],
14
+ "properties": {
15
+ "$schema": {
16
+ "type": "string",
17
+ "format": "uri",
18
+ "description": "URL of the schema this document conforms to"
19
+ },
20
+ "lafs_version": {
21
+ "type": "string",
22
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
23
+ "description": "LAFS protocol version (semantic versioning)"
24
+ },
25
+ "service": {
26
+ "type": "object",
27
+ "description": "Service identification and metadata",
28
+ "required": [
29
+ "name",
30
+ "version"
31
+ ],
32
+ "properties": {
33
+ "name": {
34
+ "type": "string",
35
+ "minLength": 1,
36
+ "maxLength": 100,
37
+ "description": "Unique service name (kebab-case recommended)"
38
+ },
39
+ "version": {
40
+ "type": "string",
41
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
42
+ "description": "Service version (semantic versioning)"
43
+ },
44
+ "description": {
45
+ "type": "string",
46
+ "maxLength": 500,
47
+ "description": "Human-readable service description"
48
+ }
49
+ },
50
+ "additionalProperties": false
51
+ },
52
+ "capabilities": {
53
+ "type": "array",
54
+ "description": "List of LAFS capabilities this service provides",
55
+ "minItems": 1,
56
+ "items": {
57
+ "type": "object",
58
+ "required": [
59
+ "name",
60
+ "version",
61
+ "operations"
62
+ ],
63
+ "properties": {
64
+ "name": {
65
+ "type": "string",
66
+ "minLength": 1,
67
+ "maxLength": 100,
68
+ "description": "Capability identifier (kebab-case recommended)"
69
+ },
70
+ "version": {
71
+ "type": "string",
72
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
73
+ "description": "Capability version (semantic versioning)"
74
+ },
75
+ "description": {
76
+ "type": "string",
77
+ "maxLength": 500,
78
+ "description": "Human-readable capability description"
79
+ },
80
+ "operations": {
81
+ "type": "array",
82
+ "description": "List of operations this capability supports",
83
+ "minItems": 1,
84
+ "items": {
85
+ "type": "string",
86
+ "minLength": 1,
87
+ "maxLength": 50
88
+ }
89
+ },
90
+ "optional": {
91
+ "type": "boolean",
92
+ "default": false,
93
+ "description": "Whether this capability is optional for clients"
94
+ }
95
+ },
96
+ "additionalProperties": false
97
+ }
98
+ },
99
+ "endpoints": {
100
+ "type": "object",
101
+ "description": "URL endpoints for LAFS operations",
102
+ "required": [
103
+ "envelope",
104
+ "discovery"
105
+ ],
106
+ "properties": {
107
+ "envelope": {
108
+ "type": "string",
109
+ "minLength": 1,
110
+ "description": "URL for envelope submission (POST)"
111
+ },
112
+ "context": {
113
+ "type": "string",
114
+ "minLength": 1,
115
+ "description": "URL for context ledger operations"
116
+ },
117
+ "discovery": {
118
+ "type": "string",
119
+ "minLength": 1,
120
+ "description": "URL of this discovery document"
121
+ }
122
+ },
123
+ "additionalProperties": false
124
+ },
125
+ "extensions": {
126
+ "type": "object",
127
+ "description": "Extension fields for vendor-specific metadata",
128
+ "additionalProperties": true
129
+ }
130
+ },
131
+ "additionalProperties": false
132
+ }