@peac/disc 0.12.13 → 0.12.14

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @peac/disc
2
2
 
3
- PEAC issuer discovery: ABNF-compliant `.well-known/peac.txt` parser, generator, and remote fetcher.
3
+ Thin loader / validator and remote fetcher for `peac.txt` policy documents.
4
4
 
5
5
  ## Installation
6
6
 
@@ -10,37 +10,65 @@ pnpm add @peac/disc
10
10
 
11
11
  ## What It Does
12
12
 
13
- `@peac/disc` parses and generates `.well-known/peac.txt` discovery documents that allow verifiers to find an issuer's public keys and policy information. It enforces the normative 20-line limit, validates document structure against the ABNF grammar, and provides a convenience `discover()` function for remote resolution.
13
+ `@peac/disc` is a thin wrapper around
14
+ [`@peac/policy-kit`](../policy-kit) specialized for the `peac.txt`
15
+ discovery surface. It:
16
+
17
+ - fetches `/.well-known/peac.txt` with `discover(origin)`,
18
+ - delegates parsing of `peac-policy/0.1` YAML / JSON bytes to
19
+ `@peac/policy-kit.parsePolicyDocument`,
20
+ - returns a tolerant `ParseResult` (rather than throwing) that carries a
21
+ validated `PolicyDocument`, error messages, and advisory warnings,
22
+ - tolerates legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`)
23
+ in older example documents by stripping them before validation and
24
+ surfacing a structured `PEAC_LEGACY_PEAC_TXT_KEY_FIELD`
25
+ `DeprecationWarning`.
26
+
27
+ `peac.txt` is the **policy-document surface** per
28
+ `docs/specs/PEAC-TXT.md`. It is **not** a key discovery surface.
29
+ Cryptographic key resolution uses the normative chain
30
+ `iss` -> `/.well-known/peac-issuer.json` -> `jwks_uri` -> JWKS (see
31
+ `docs/specs/PEAC-ISSUER.md`). For that flow, use `parseIssuerConfig` /
32
+ `fetchIssuerConfig` from `@peac/protocol`.
14
33
 
15
34
  ## How Do I Use It?
16
35
 
17
- ### Parse a discovery document
36
+ ### Parse a policy document
18
37
 
19
38
  ```typescript
20
- import { parse, validate } from '@peac/disc';
39
+ import { parse } from '@peac/disc';
21
40
 
22
41
  const result = parse(`
23
- version: peac/0.1
24
- issuer: https://example.com
25
- jwks: https://example.com/.well-known/jwks.json
42
+ version: 'peac-policy/0.1'
43
+ defaults:
44
+ decision: deny
45
+ rules:
46
+ - name: allow-verified-agents
47
+ subject:
48
+ type: agent
49
+ labels: [verified]
50
+ purpose: inference
51
+ decision: allow
26
52
  `);
27
53
 
28
54
  if (result.valid) {
29
- console.log(result.discovery.issuer); // 'https://example.com'
55
+ console.log(result.data?.version); // 'peac-policy/0.1'
56
+ console.log(result.data?.rules[0].decision); // 'allow'
57
+ }
58
+
59
+ if (result.warnings) {
60
+ // e.g. legacy key-discovery lines were stripped on parse
61
+ console.warn(result.warnings);
30
62
  }
31
63
  ```
32
64
 
33
- ### Generate a discovery document
65
+ ### Emit a policy document as YAML
34
66
 
35
67
  ```typescript
36
68
  import { emit } from '@peac/disc';
69
+ import { createExamplePolicy } from '@peac/policy-kit';
37
70
 
38
- const txt = emit({
39
- version: 'peac/0.1',
40
- issuer: 'https://example.com',
41
- jwks_uri: 'https://example.com/.well-known/jwks.json',
42
- });
43
-
71
+ const yaml = emit(createExamplePolicy());
44
72
  // Serve at /.well-known/peac.txt
45
73
  ```
46
74
 
@@ -51,25 +79,30 @@ import { discover, WELL_KNOWN_PATH } from '@peac/disc';
51
79
 
52
80
  const result = await discover('https://example.com');
53
81
  if (result.valid) {
54
- console.log(result.discovery);
82
+ console.log(result.data);
55
83
  }
56
-
57
84
  console.log(WELL_KNOWN_PATH); // '/.well-known/peac.txt'
58
85
  ```
59
86
 
60
- ## Integrates With
87
+ The caller's user-agent is taken from the `PEAC_USER_AGENT` environment
88
+ variable when present; otherwise `peac-disc` is used. `@peac/disc` does
89
+ not hard-code a package version in the user-agent (runtime-visible
90
+ version constants belong in release tooling).
61
91
 
62
- - `@peac/policy-kit`: Policy compilation generates `peac.txt` artifacts
63
- - `@peac/protocol` (Layer 3): Issuer resolution during receipt verification
64
- - `@peac/jwks-cache`: Fetches JWKS from the URI discovered via `peac.txt`
92
+ ## Limits
65
93
 
66
- ## For Agent Developers
94
+ Per `docs/specs/PEAC-TXT.md` §6.1, remote documents larger than
95
+ **256 KiB** are rejected by `discover()`. Nesting depth, array length,
96
+ and string length limits are enforced by the underlying
97
+ `@peac/policy-kit` validator.
67
98
 
68
- If you are building an AI agent or MCP server that needs evidence receipts:
99
+ ## Integrates With
69
100
 
70
- - Start with [`@peac/mcp-server`](https://www.npmjs.com/package/@peac/mcp-server) for a ready-to-use MCP tool server
71
- - Use `@peac/protocol` for programmatic receipt issuance and verification
72
- - See the [llms.txt](https://github.com/peacprotocol/peac/blob/main/llms.txt) for a concise overview
101
+ - `@peac/policy-kit`: canonical compiler / parser / evaluator for
102
+ `peac-policy/0.1` documents. `@peac/disc.parse` delegates to
103
+ `@peac/policy-kit.parsePolicyDocument`.
104
+ - `@peac/protocol`: `parseIssuerConfig` / `fetchIssuerConfig` for the
105
+ normative key-discovery chain.
73
106
 
74
107
  ## License
75
108
 
@@ -77,6 +110,7 @@ Apache-2.0
77
110
 
78
111
  ---
79
112
 
80
- PEAC Protocol is an open source project stewarded by Originary and community contributors.
113
+ PEAC Protocol is an open source project stewarded by Originary and community
114
+ contributors.
81
115
 
82
116
  [Docs](https://www.peacprotocol.org) | [GitHub](https://github.com/peacprotocol/peac) | [Originary](https://www.originary.xyz)
package/dist/index.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var policyKit = require('@peac/policy-kit');
4
+
3
5
  var __defProp = Object.defineProperty;
4
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
7
  var __esm = (fn, res) => function __init() {
@@ -13,162 +15,153 @@ var __export = (target, all) => {
13
15
  // src/parser.ts
14
16
  var parser_exports = {};
15
17
  __export(parser_exports, {
18
+ __resetLegacyWarningForTests: () => __resetLegacyWarningForTests,
16
19
  emit: () => emit,
17
20
  parse: () => parse,
18
21
  validate: () => validate
19
22
  });
20
- function parse(content, options = {}) {
21
- const maxLines = options.maxLines ?? MAX_LINES;
22
- const errors = [];
23
- const data = {};
24
- const lines = content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
25
- if (lines.length > maxLines) {
23
+ function fireLegacyWarning(field) {
24
+ if (legacyWarningFired) return;
25
+ legacyWarningFired = true;
26
+ if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
27
+ process.emitWarning(
28
+ `peac.txt legacy key-discovery field "${field}" is deprecated and ignored. peac.txt is a policy-document surface (docs/specs/PEAC-TXT.md). Key resolution uses iss -> /.well-known/peac-issuer.json -> jwks_uri -> JWKS.`,
29
+ { code: "PEAC_LEGACY_PEAC_TXT_KEY_FIELD", type: "DeprecationWarning" }
30
+ );
31
+ }
32
+ }
33
+ function __resetLegacyWarningForTests() {
34
+ legacyWarningFired = false;
35
+ }
36
+ function collectLegacyWarnings(text) {
37
+ const warnings = [];
38
+ let firstField = null;
39
+ const lines = text.split(/\r?\n/);
40
+ lines.forEach((line, idx) => {
41
+ const match = line.match(/^\s*(verify|public_keys|jwks)\s*:/);
42
+ if (match) {
43
+ if (firstField === null) firstField = match[1];
44
+ warnings.push(
45
+ `Line ${idx + 1}: legacy key-discovery field "${match[1]}" ignored (peac.txt is policy-only; use peac-issuer.json for keys)`
46
+ );
47
+ }
48
+ });
49
+ return { warnings, firstField };
50
+ }
51
+ function parse(text) {
52
+ const warnings = [];
53
+ if (text.trim().length === 0) {
26
54
  return {
27
55
  valid: false,
28
- errors: [`Line limit exceeded: ${lines.length} > ${maxLines}`],
29
- lineCount: lines.length
56
+ errors: ["Empty policy document. Expected peac-policy/0.1 YAML or JSON."]
30
57
  };
31
58
  }
32
- for (const [index, line] of lines.entries()) {
33
- let matched = false;
34
- for (const [field, pattern] of Object.entries(FIELD_PATTERNS)) {
35
- const match = line.match(pattern);
36
- if (match) {
37
- matched = true;
38
- try {
39
- switch (field) {
40
- case "preferences":
41
- case "access_control":
42
- case "provenance":
43
- case "verify":
44
- data[field] = match[1].trim();
45
- break;
46
- case "receipts":
47
- data.receipts = match[1];
48
- break;
49
- case "payments":
50
- data.payments = parseArray(match[1]);
51
- break;
52
- case "public_keys":
53
- data.public_keys = parsePublicKeys(match[1]);
54
- break;
55
- }
56
- } catch (error) {
57
- errors.push(
58
- `Line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`
59
- );
60
- }
61
- break;
62
- }
59
+ const hasLegacyLines = LEGACY_KEY_LINE.test(text);
60
+ try {
61
+ const data = policyKit.parsePolicyDocument(text);
62
+ if (hasLegacyLines) {
63
+ const legacy = collectLegacyWarnings(text);
64
+ warnings.push(...legacy.warnings);
65
+ if (legacy.firstField) fireLegacyWarning(legacy.firstField);
63
66
  }
64
- if (!matched) {
65
- errors.push(`Line ${index + 1}: Invalid format: ${line}`);
67
+ return {
68
+ valid: true,
69
+ data,
70
+ warnings: warnings.length > 0 ? warnings : void 0
71
+ };
72
+ } catch (firstErr) {
73
+ if (!hasLegacyLines) {
74
+ return failure(firstErr, warnings);
66
75
  }
67
- }
68
- if (!data.verify) {
69
- errors.push("Missing required field: verify");
70
- }
71
- return {
72
- valid: errors.length === 0,
73
- data: errors.length === 0 ? data : void 0,
74
- errors: errors.length > 0 ? errors : void 0,
75
- lineCount: lines.length
76
- };
77
- }
78
- function parseArray(content) {
79
- return content.split(",").map((item) => item.trim().replace(/^["']|["']$/g, "")).filter((item) => item.length > 0);
80
- }
81
- function parsePublicKeys(content) {
82
- const keyStrings = parseArray(content);
83
- const keys = [];
84
- for (const keyString of keyStrings) {
85
- const keyMatch = keyString.match(/^([^:]+):([^:]+):(.+)$/);
86
- if (!keyMatch) {
87
- throw new Error(`Invalid public key format: ${keyString}`);
76
+ const legacy = collectLegacyWarnings(text);
77
+ warnings.push(...legacy.warnings);
78
+ if (legacy.firstField) fireLegacyWarning(legacy.firstField);
79
+ const stripped = text.replace(LEGACY_KEY_FULL_LINE_GLOBAL, "");
80
+ if (stripped.trim().length === 0) {
81
+ return {
82
+ valid: false,
83
+ errors: ["Empty policy document after stripping legacy key-discovery lines."],
84
+ warnings: warnings.length > 0 ? warnings : void 0
85
+ };
86
+ }
87
+ try {
88
+ const data = policyKit.parsePolicyDocument(stripped);
89
+ return {
90
+ valid: true,
91
+ data,
92
+ warnings: warnings.length > 0 ? warnings : void 0
93
+ };
94
+ } catch (retryErr) {
95
+ return failure(retryErr, warnings);
88
96
  }
89
- keys.push({
90
- kid: keyMatch[1],
91
- alg: keyMatch[2],
92
- key: keyMatch[3]
93
- });
94
97
  }
95
- return keys;
96
98
  }
97
- function assertSafeFieldValue(value, fieldName) {
98
- if (UNSAFE_FIELD_CHARS.test(value)) {
99
- throw new Error(
100
- `Invalid ${fieldName}: must not contain quotes, colons, brackets, newlines, or control characters`
101
- );
99
+ function failure(err, warnings) {
100
+ if (err instanceof policyKit.PolicyValidationError || err instanceof policyKit.PolicyLoadError) {
101
+ return {
102
+ valid: false,
103
+ errors: [err.message],
104
+ warnings: warnings.length > 0 ? warnings : void 0
105
+ };
102
106
  }
107
+ return {
108
+ valid: false,
109
+ errors: [err instanceof Error ? err.message : String(err)],
110
+ warnings: warnings.length > 0 ? warnings : void 0
111
+ };
103
112
  }
104
- function emit(data) {
105
- const lines = [];
106
- if (data.preferences) {
107
- lines.push(`preferences: ${data.preferences}`);
108
- }
109
- if (data.access_control) {
110
- lines.push(`access_control: ${data.access_control}`);
111
- }
112
- if (data.payments && data.payments.length > 0) {
113
- data.payments.forEach((p) => assertSafeFieldValue(p, "payment"));
114
- const paymentsStr = data.payments.map((p) => `"${p}"`).join(", ");
115
- lines.push(`payments: [${paymentsStr}]`);
116
- }
117
- if (data.provenance) {
118
- lines.push(`provenance: ${data.provenance}`);
119
- }
120
- if (data.receipts) {
121
- lines.push(`receipts: ${data.receipts}`);
122
- }
123
- if (data.verify) {
124
- lines.push(`verify: ${data.verify}`);
125
- }
126
- if (data.public_keys && data.public_keys.length > 0) {
127
- data.public_keys.forEach((k) => {
128
- assertSafeFieldValue(k.kid, "kid");
129
- assertSafeFieldValue(k.alg, "alg");
130
- assertSafeFieldValue(k.key, "key");
131
- });
132
- const keysStr = data.public_keys.map((k) => `"${k.kid}:${k.alg}:${k.key}"`).join(", ");
133
- lines.push(`public_keys: [${keysStr}]`);
134
- }
135
- if (lines.length > MAX_LINES) {
136
- throw new Error(`Generated peac.txt exceeds ${MAX_LINES} lines: ${lines.length}`);
137
- }
138
- return lines.join("\n");
113
+ function emit(doc) {
114
+ return policyKit.serializePolicyYaml(doc);
139
115
  }
140
- function validate(content) {
141
- const result = parse(content);
142
- return result.valid;
116
+ function validate(text) {
117
+ return parse(text).valid;
143
118
  }
144
- var MAX_LINES, FIELD_PATTERNS, UNSAFE_FIELD_CHARS;
119
+ var LEGACY_KEY_LINE, LEGACY_KEY_FULL_LINE_GLOBAL, legacyWarningFired;
145
120
  var init_parser = __esm({
146
121
  "src/parser.ts"() {
147
- MAX_LINES = 20;
148
- FIELD_PATTERNS = {
149
- preferences: /^preferences:\s*(.+)$/,
150
- access_control: /^access_control:\s*(.+)$/,
151
- payments: /^payments:\s*\[([^\]]+)\]$/,
152
- provenance: /^provenance:\s*(.+)$/,
153
- receipts: /^receipts:\s*(required|optional)$/,
154
- verify: /^verify:\s*(.+)$/,
155
- public_keys: /^public_keys:\s*\[([^\]]+)\]$/
156
- };
157
- UNSAFE_FIELD_CHARS = /["\n\r\x00-\x1f:[\]]/;
122
+ LEGACY_KEY_LINE = /^\s*(verify|public_keys|jwks)\s*:/m;
123
+ LEGACY_KEY_FULL_LINE_GLOBAL = /^\s*(verify|public_keys|jwks)\s*:.*\r?\n?/gm;
124
+ legacyWarningFired = false;
158
125
  }
159
126
  });
160
127
 
161
128
  // src/index.ts
162
129
  init_parser();
163
- var VERSION = "0.9.15";
164
- var MAX_LINES2 = 20;
130
+ var MAX_BYTES = 262144;
165
131
  var WELL_KNOWN_PATH = "/.well-known/peac.txt";
166
- var UA = `PEAC/${VERSION} (+https://www.peacprotocol.org)`;
167
- async function discover(origin) {
132
+ var DEFAULT_TIMEOUT_MS = 5e3;
133
+ var DEFAULT_USER_AGENT = "peac-disc";
134
+ async function discover(origin, options = {}) {
135
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
136
+ if (typeof fetchImpl !== "function") {
137
+ return {
138
+ valid: false,
139
+ errors: [
140
+ "Discovery failed: no fetch implementation available (supply options.fetchImpl or provide a global fetch)"
141
+ ]
142
+ };
143
+ }
144
+ const envUa = typeof process !== "undefined" && typeof process.env === "object" ? process.env.PEAC_USER_AGENT : void 0;
145
+ const userAgent = options.userAgent ?? envUa ?? DEFAULT_USER_AGENT;
146
+ const maxBytes = options.maxBytes ?? MAX_BYTES;
147
+ const redirect = options.redirect ?? "error";
148
+ let localController;
149
+ let timer;
150
+ let signal = options.signal;
151
+ if (!signal) {
152
+ localController = new AbortController();
153
+ signal = localController.signal;
154
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
155
+ if (timeoutMs > 0 && Number.isFinite(timeoutMs)) {
156
+ timer = setTimeout(() => localController?.abort(), timeoutMs);
157
+ }
158
+ }
168
159
  try {
169
160
  const url = new URL(WELL_KNOWN_PATH, origin);
170
- const response = await fetch(url.toString(), {
171
- headers: { "User-Agent": UA }
161
+ const response = await fetchImpl(url.toString(), {
162
+ headers: { "User-Agent": userAgent },
163
+ signal,
164
+ redirect
172
165
  });
173
166
  if (!response.ok) {
174
167
  return {
@@ -177,6 +170,12 @@ async function discover(origin) {
177
170
  };
178
171
  }
179
172
  const content = await response.text();
173
+ if (content.length > maxBytes) {
174
+ return {
175
+ valid: false,
176
+ errors: [`peac.txt exceeds ${maxBytes} bytes (got ${content.length})`]
177
+ };
178
+ }
180
179
  const { parse: parse2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
181
180
  return parse2(content);
182
181
  } catch (error) {
@@ -184,12 +183,15 @@ async function discover(origin) {
184
183
  valid: false,
185
184
  errors: [`Discovery failed: ${error instanceof Error ? error.message : String(error)}`]
186
185
  };
186
+ } finally {
187
+ if (timer) clearTimeout(timer);
187
188
  }
188
189
  }
189
190
 
190
- exports.MAX_LINES = MAX_LINES2;
191
- exports.VERSION = VERSION;
191
+ exports.DEFAULT_TIMEOUT_MS = DEFAULT_TIMEOUT_MS;
192
+ exports.MAX_BYTES = MAX_BYTES;
192
193
  exports.WELL_KNOWN_PATH = WELL_KNOWN_PATH;
194
+ exports.__resetLegacyWarningForTests = __resetLegacyWarningForTests;
193
195
  exports.discover = discover;
194
196
  exports.emit = emit;
195
197
  exports.parse = parse;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser.ts","../src/index.ts"],"names":["MAX_LINES","parse"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @peac/disc/parser - peac.txt parser with ≤20 lines enforcement\n * ABNF-compliant discovery document parsing\n */\n\nimport type { PeacDiscovery, ParseResult, PublicKeyInfo, ValidationOptions } from './types.js';\n\nconst MAX_LINES = 20;\nconst FIELD_PATTERNS = {\n preferences: /^preferences:\\s*(.+)$/,\n access_control: /^access_control:\\s*(.+)$/,\n payments: /^payments:\\s*\\[([^\\]]+)\\]$/,\n provenance: /^provenance:\\s*(.+)$/,\n receipts: /^receipts:\\s*(required|optional)$/,\n verify: /^verify:\\s*(.+)$/,\n public_keys: /^public_keys:\\s*\\[([^\\]]+)\\]$/,\n};\n\nexport function parse(content: string, options: ValidationOptions = {}): ParseResult {\n const maxLines = options.maxLines ?? MAX_LINES;\n const errors: string[] = [];\n const data: PeacDiscovery = {};\n\n const lines = content\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l && !l.startsWith('#'));\n\n // Enforce line limit\n if (lines.length > maxLines) {\n return {\n valid: false,\n errors: [`Line limit exceeded: ${lines.length} > ${maxLines}`],\n lineCount: lines.length,\n };\n }\n\n // Parse each line\n for (const [index, line] of lines.entries()) {\n let matched = false;\n\n for (const [field, pattern] of Object.entries(FIELD_PATTERNS)) {\n const match = line.match(pattern);\n if (match) {\n matched = true;\n try {\n switch (field) {\n case 'preferences':\n case 'access_control':\n case 'provenance':\n case 'verify':\n data[field] = match[1].trim();\n break;\n case 'receipts':\n data.receipts = match[1] as 'required' | 'optional';\n break;\n case 'payments':\n data.payments = parseArray(match[1]);\n break;\n case 'public_keys':\n data.public_keys = parsePublicKeys(match[1]);\n break;\n }\n } catch (error) {\n errors.push(\n `Line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n break;\n }\n }\n\n if (!matched) {\n errors.push(`Line ${index + 1}: Invalid format: ${line}`);\n }\n }\n\n // Validate required fields\n if (!data.verify) {\n errors.push('Missing required field: verify');\n }\n\n return {\n valid: errors.length === 0,\n data: errors.length === 0 ? data : undefined,\n errors: errors.length > 0 ? errors : undefined,\n lineCount: lines.length,\n };\n}\n\nfunction parseArray(content: string): string[] {\n return content\n .split(',')\n .map((item) => item.trim().replace(/^[\"']|[\"']$/g, ''))\n .filter((item) => item.length > 0);\n}\n\nfunction parsePublicKeys(content: string): PublicKeyInfo[] {\n const keyStrings = parseArray(content);\n const keys: PublicKeyInfo[] = [];\n\n for (const keyString of keyStrings) {\n const keyMatch = keyString.match(/^([^:]+):([^:]+):(.+)$/);\n if (!keyMatch) {\n throw new Error(`Invalid public key format: ${keyString}`);\n }\n\n keys.push({\n kid: keyMatch[1],\n alg: keyMatch[2],\n key: keyMatch[3],\n });\n }\n\n return keys;\n}\n\n/** Characters that break peac.txt wire format: quotes, colons, brackets, control chars */\nconst UNSAFE_FIELD_CHARS = /[\"\\n\\r\\x00-\\x1f:[\\]]/;\n\nfunction assertSafeFieldValue(value: string, fieldName: string): void {\n if (UNSAFE_FIELD_CHARS.test(value)) {\n throw new Error(\n `Invalid ${fieldName}: must not contain quotes, colons, brackets, newlines, or control characters`\n );\n }\n}\n\nexport function emit(data: PeacDiscovery): string {\n const lines: string[] = [];\n\n if (data.preferences) {\n lines.push(`preferences: ${data.preferences}`);\n }\n\n if (data.access_control) {\n lines.push(`access_control: ${data.access_control}`);\n }\n\n if (data.payments && data.payments.length > 0) {\n data.payments.forEach((p) => assertSafeFieldValue(p, 'payment'));\n const paymentsStr = data.payments.map((p) => `\"${p}\"`).join(', ');\n lines.push(`payments: [${paymentsStr}]`);\n }\n\n if (data.provenance) {\n lines.push(`provenance: ${data.provenance}`);\n }\n\n if (data.receipts) {\n lines.push(`receipts: ${data.receipts}`);\n }\n\n if (data.verify) {\n lines.push(`verify: ${data.verify}`);\n }\n\n if (data.public_keys && data.public_keys.length > 0) {\n data.public_keys.forEach((k) => {\n assertSafeFieldValue(k.kid, 'kid');\n assertSafeFieldValue(k.alg, 'alg');\n assertSafeFieldValue(k.key, 'key');\n });\n const keysStr = data.public_keys.map((k) => `\"${k.kid}:${k.alg}:${k.key}\"`).join(', ');\n lines.push(`public_keys: [${keysStr}]`);\n }\n\n // Enforce line limit during emission\n if (lines.length > MAX_LINES) {\n throw new Error(`Generated peac.txt exceeds ${MAX_LINES} lines: ${lines.length}`);\n }\n\n return lines.join('\\n');\n}\n\nexport function validate(content: string): boolean {\n const result = parse(content);\n return result.valid;\n}\n","/**\n * @peac/disc - PEAC discovery with ≤20 lines enforcement\n * ABNF-compliant .well-known/peac.txt parser and generator\n */\n\nexport { parse, emit, validate } from './parser.js';\nexport type { PeacDiscovery, PublicKeyInfo, ParseResult, ValidationOptions } from './types.js';\n\n// Constants\nexport const VERSION = '0.9.15';\nexport const MAX_LINES = 20;\nexport const WELL_KNOWN_PATH = '/.well-known/peac.txt';\n\nconst UA = `PEAC/${VERSION} (+https://www.peacprotocol.org)`;\n\n// Convenience function for fetching and parsing discovery documents\nexport async function discover(origin: string): Promise<import('./types.js').ParseResult> {\n try {\n const url = new URL(WELL_KNOWN_PATH, origin);\n const response = await fetch(url.toString(), {\n headers: { 'User-Agent': UA },\n });\n\n if (!response.ok) {\n return {\n valid: false,\n errors: [`HTTP ${response.status}: ${response.statusText}`],\n };\n }\n\n const content = await response.text();\n const { parse } = await import('./parser.js');\n return parse(content);\n } catch (error) {\n return {\n valid: false,\n errors: [`Discovery failed: ${error instanceof Error ? error.message : String(error)}`],\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/parser.ts","../src/index.ts"],"names":["parsePolicyDocument","PolicyValidationError","PolicyLoadError","serializePolicyYaml","parse"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * @peac/disc/parser - thin peac.txt policy-document loader/validator.\n *\n * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md.\n * Full parsing is delegated to `@peac/policy-kit.parsePolicyDocument`;\n * this module only provides:\n *\n * - format detection (YAML vs JSON) per PEAC-TXT.md §5.1\n * - a tolerant `parse()` wrapper that returns a structured `ParseResult`\n * (rather than throwing)\n * - structured warnings for legacy key-discovery lines (`verify`,\n * `public_keys`, `jwks`) that appeared in pre-v0.12.14 peac.txt\n * examples. Those lines are NEVER honored here: key discovery flows\n * through `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS\n * (docs/specs/PEAC-ISSUER.md).\n * - a tiny `emit()` helper that serializes a `PolicyDocument` via\n * `@peac/policy-kit.serializePolicyYaml`\n *\n * @see docs/specs/PEAC-TXT.md\n * @see docs/specs/PEAC-ISSUER.md\n */\n\nimport {\n PolicyLoadError,\n PolicyValidationError,\n parsePolicyDocument,\n serializePolicyYaml,\n type PolicyDocument,\n} from '@peac/policy-kit';\nimport type { ParseResult } from './types.js';\n\nconst LEGACY_KEY_LINE = /^\\s*(verify|public_keys|jwks)\\s*:/m;\n/** Strips the whole line (including the trailing newline) when matched. */\nconst LEGACY_KEY_FULL_LINE_GLOBAL = /^\\s*(verify|public_keys|jwks)\\s*:.*\\r?\\n?/gm;\n\nlet legacyWarningFired = false;\n\nfunction fireLegacyWarning(field: string): void {\n if (legacyWarningFired) return;\n legacyWarningFired = true;\n if (typeof process !== 'undefined' && typeof process.emitWarning === 'function') {\n process.emitWarning(\n `peac.txt legacy key-discovery field \"${field}\" is deprecated and ignored. ` +\n `peac.txt is a policy-document surface (docs/specs/PEAC-TXT.md). ` +\n `Key resolution uses iss -> /.well-known/peac-issuer.json -> jwks_uri -> JWKS.`,\n { code: 'PEAC_LEGACY_PEAC_TXT_KEY_FIELD', type: 'DeprecationWarning' }\n );\n }\n}\n\n/**\n * Reset the one-shot legacy-warning flag. Exposed for tests that need to\n * observe the warning more than once per process.\n */\nexport function __resetLegacyWarningForTests(): void {\n legacyWarningFired = false;\n}\n\nfunction collectLegacyWarnings(text: string): { warnings: string[]; firstField: string | null } {\n const warnings: string[] = [];\n let firstField: string | null = null;\n const lines = text.split(/\\r?\\n/);\n lines.forEach((line, idx) => {\n const match = line.match(/^\\s*(verify|public_keys|jwks)\\s*:/);\n if (match) {\n if (firstField === null) firstField = match[1];\n warnings.push(\n `Line ${idx + 1}: legacy key-discovery field \"${match[1]}\" ignored ` +\n `(peac.txt is policy-only; use peac-issuer.json for keys)`\n );\n }\n });\n return { warnings, firstField };\n}\n\n/**\n * Parse a peac.txt policy document. Accepts YAML or JSON per\n * `docs/specs/PEAC-TXT.md` §5.1. On success, `data` is the validated\n * `peac-policy/0.1` `PolicyDocument`.\n *\n * Legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`) are\n * tolerated via a two-pass strategy: first the raw bytes are handed to\n * `parsePolicyDocument`; if validation fails AND top-level legacy lines\n * are present, the legacy lines are stripped and parsing is retried\n * once. Detected legacy lines are listed in `warnings` and surface a\n * structured `PEAC_LEGACY_PEAC_TXT_KEY_FIELD` `DeprecationWarning` once\n * per process. They never populate the parsed result. This preserves\n * the original bytes when a policy document happens to mention those\n * tokens inside comments, block scalars, or rule text.\n */\nexport function parse(text: string): ParseResult {\n const warnings: string[] = [];\n\n if (text.trim().length === 0) {\n return {\n valid: false,\n errors: ['Empty policy document. Expected peac-policy/0.1 YAML or JSON.'],\n };\n }\n\n const hasLegacyLines = LEGACY_KEY_LINE.test(text);\n\n // First pass: try the raw bytes. If they parse cleanly, legacy-looking\n // substrings inside block scalars / comments / rule text are not\n // mutated.\n try {\n const data = parsePolicyDocument(text);\n if (hasLegacyLines) {\n const legacy = collectLegacyWarnings(text);\n warnings.push(...legacy.warnings);\n if (legacy.firstField) fireLegacyWarning(legacy.firstField);\n }\n return {\n valid: true,\n data,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (firstErr) {\n if (!hasLegacyLines) {\n return failure(firstErr, warnings);\n }\n // Second pass: strip top-level legacy key-discovery lines and retry.\n const legacy = collectLegacyWarnings(text);\n warnings.push(...legacy.warnings);\n if (legacy.firstField) fireLegacyWarning(legacy.firstField);\n\n const stripped = text.replace(LEGACY_KEY_FULL_LINE_GLOBAL, '');\n if (stripped.trim().length === 0) {\n return {\n valid: false,\n errors: ['Empty policy document after stripping legacy key-discovery lines.'],\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n try {\n const data = parsePolicyDocument(stripped);\n return {\n valid: true,\n data,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (retryErr) {\n return failure(retryErr, warnings);\n }\n }\n}\n\nfunction failure(err: unknown, warnings: string[]): ParseResult {\n if (err instanceof PolicyValidationError || err instanceof PolicyLoadError) {\n return {\n valid: false,\n errors: [err.message],\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n return {\n valid: false,\n errors: [err instanceof Error ? err.message : String(err)],\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\n/**\n * Serialize a `peac-policy/0.1` `PolicyDocument` as YAML suitable for\n * serving at `/.well-known/peac.txt`. Delegates to\n * `@peac/policy-kit.serializePolicyYaml`.\n */\nexport function emit(doc: PolicyDocument): string {\n return serializePolicyYaml(doc);\n}\n\n/**\n * Convenience predicate: returns `true` iff `text` parses as a valid\n * `peac-policy/0.1` document.\n */\nexport function validate(text: string): boolean {\n return parse(text).valid;\n}\n","/**\n * @peac/disc - thin peac.txt policy-document loader/validator and remote fetcher.\n *\n * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md. Full\n * parsing is delegated to `@peac/policy-kit.parsePolicyDocument`; this\n * package provides a tolerant `parse()` wrapper, a `discover()` remote\n * fetcher, and structured warnings for legacy key-discovery lines that\n * appeared in older peac.txt examples.\n *\n * `peac.txt` is NOT a key discovery surface. Cryptographic key resolution\n * flows through `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS\n * (docs/specs/PEAC-ISSUER.md). Callers that need key material MUST use\n * `parseIssuerConfig` / `fetchIssuerConfig` from `@peac/protocol`.\n *\n * Legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`) are\n * tolerated on parse: they are stripped before validation, surfaced on\n * `ParseResult.warnings`, and fire a structured `process.emitWarning`\n * with code `PEAC_LEGACY_PEAC_TXT_KEY_FIELD` once per process.\n */\n\nexport { parse, emit, validate, __resetLegacyWarningForTests } from './parser.js';\nexport type { ParseResult, ValidationOptions, PolicyDocument } from './types.js';\n\n/**\n * @deprecated Retained for one minor to keep existing import paths\n * compiling. peac.txt policy documents now resolve to a `PolicyDocument`\n * (re-exported from `@peac/policy-kit`). Removal target: next cleanup\n * release.\n */\nexport type { PeacDiscovery, PublicKeyInfo } from './types.js';\n\nexport const MAX_BYTES = 262144; // 256 KiB, per docs/specs/PEAC-TXT.md §6.1\nexport const WELL_KNOWN_PATH = '/.well-known/peac.txt';\nexport const DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_USER_AGENT = 'peac-disc';\n\n/**\n * Minimal fetch signature accepted by `discover`. `undici` / `node-fetch` /\n * browser / test-double implementations all satisfy this.\n */\nexport type DiscoverFetch = (\n input: string,\n init?: {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n redirect?: 'follow' | 'error' | 'manual';\n }\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n text(): Promise<string>;\n}>;\n\nexport interface DiscoverOptions {\n /**\n * HTTP fetch implementation. Defaults to the ambient `fetch` global.\n * Supply `undici.fetch`, a test double, or a policy-wrapping client as\n * needed.\n */\n fetchImpl?: DiscoverFetch;\n /**\n * User-agent string. Precedence (highest first): this option, the\n * `PEAC_USER_AGENT` environment variable, then `peac-disc`.\n */\n userAgent?: string;\n /** Caller-supplied abort signal. */\n signal?: AbortSignal;\n /**\n * Millisecond timeout. Ignored when `signal` is supplied (the caller\n * owns cancellation). Defaults to 5_000 when neither is provided.\n */\n timeoutMs?: number;\n /** Override the 256 KiB body cap from docs/specs/PEAC-TXT.md §6.1. */\n maxBytes?: number;\n /**\n * Redirect policy. Defaults to `error` to avoid cross-origin surprise\n * on a well-known discovery endpoint; set to `follow` explicitly if the\n * deployment relies on server-side redirects.\n */\n redirect?: 'follow' | 'error' | 'manual';\n}\n\n/**\n * Fetch and parse a remote peac.txt policy document. On success returns a\n * `ParseResult` whose `data` is the validated `peac-policy/0.1`\n * `PolicyDocument`. Legacy key-discovery lines in the fetched bytes are\n * surfaced as warnings but never populate `data`.\n */\nexport async function discover(\n origin: string,\n options: DiscoverOptions = {}\n): Promise<import('./types.js').ParseResult> {\n const fetchImpl = (options.fetchImpl ?? (globalThis as { fetch?: DiscoverFetch }).fetch) as\n | DiscoverFetch\n | undefined;\n if (typeof fetchImpl !== 'function') {\n return {\n valid: false,\n errors: [\n 'Discovery failed: no fetch implementation available (supply options.fetchImpl or provide a global fetch)',\n ],\n };\n }\n\n const envUa =\n typeof process !== 'undefined' && typeof process.env === 'object'\n ? process.env.PEAC_USER_AGENT\n : undefined;\n const userAgent = options.userAgent ?? envUa ?? DEFAULT_USER_AGENT;\n const maxBytes = options.maxBytes ?? MAX_BYTES;\n const redirect = options.redirect ?? 'error';\n\n // If the caller did not supply an AbortSignal, install a local one driven by timeoutMs.\n let localController: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let signal = options.signal;\n if (!signal) {\n localController = new AbortController();\n signal = localController.signal;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (timeoutMs > 0 && Number.isFinite(timeoutMs)) {\n timer = setTimeout(() => localController?.abort(), timeoutMs);\n }\n }\n\n try {\n const url = new URL(WELL_KNOWN_PATH, origin);\n const response = await fetchImpl(url.toString(), {\n headers: { 'User-Agent': userAgent },\n signal,\n redirect,\n });\n\n if (!response.ok) {\n return {\n valid: false,\n errors: [`HTTP ${response.status}: ${response.statusText}`],\n };\n }\n\n const content = await response.text();\n if (content.length > maxBytes) {\n return {\n valid: false,\n errors: [`peac.txt exceeds ${maxBytes} bytes (got ${content.length})`],\n };\n }\n const { parse } = await import('./parser.js');\n return parse(content);\n } catch (error) {\n return {\n valid: false,\n errors: [`Discovery failed: ${error instanceof Error ? error.message : String(error)}`],\n };\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,11 +1,81 @@
1
1
  /**
2
- * @peac/disc - PEAC discovery with ≤20 lines enforcement
3
- * ABNF-compliant .well-known/peac.txt parser and generator
2
+ * @peac/disc - thin peac.txt policy-document loader/validator and remote fetcher.
3
+ *
4
+ * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md. Full
5
+ * parsing is delegated to `@peac/policy-kit.parsePolicyDocument`; this
6
+ * package provides a tolerant `parse()` wrapper, a `discover()` remote
7
+ * fetcher, and structured warnings for legacy key-discovery lines that
8
+ * appeared in older peac.txt examples.
9
+ *
10
+ * `peac.txt` is NOT a key discovery surface. Cryptographic key resolution
11
+ * flows through `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS
12
+ * (docs/specs/PEAC-ISSUER.md). Callers that need key material MUST use
13
+ * `parseIssuerConfig` / `fetchIssuerConfig` from `@peac/protocol`.
14
+ *
15
+ * Legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`) are
16
+ * tolerated on parse: they are stripped before validation, surfaced on
17
+ * `ParseResult.warnings`, and fire a structured `process.emitWarning`
18
+ * with code `PEAC_LEGACY_PEAC_TXT_KEY_FIELD` once per process.
4
19
  */
5
- export { parse, emit, validate } from './parser.js';
6
- export type { PeacDiscovery, PublicKeyInfo, ParseResult, ValidationOptions } from './types.js';
7
- export declare const VERSION = "0.9.15";
8
- export declare const MAX_LINES = 20;
20
+ export { parse, emit, validate, __resetLegacyWarningForTests } from './parser.js';
21
+ export type { ParseResult, ValidationOptions, PolicyDocument } from './types.js';
22
+ /**
23
+ * @deprecated Retained for one minor to keep existing import paths
24
+ * compiling. peac.txt policy documents now resolve to a `PolicyDocument`
25
+ * (re-exported from `@peac/policy-kit`). Removal target: next cleanup
26
+ * release.
27
+ */
28
+ export type { PeacDiscovery, PublicKeyInfo } from './types.js';
29
+ export declare const MAX_BYTES = 262144;
9
30
  export declare const WELL_KNOWN_PATH = "/.well-known/peac.txt";
10
- export declare function discover(origin: string): Promise<import('./types.js').ParseResult>;
31
+ export declare const DEFAULT_TIMEOUT_MS = 5000;
32
+ /**
33
+ * Minimal fetch signature accepted by `discover`. `undici` / `node-fetch` /
34
+ * browser / test-double implementations all satisfy this.
35
+ */
36
+ export type DiscoverFetch = (input: string, init?: {
37
+ headers?: Record<string, string>;
38
+ signal?: AbortSignal;
39
+ redirect?: 'follow' | 'error' | 'manual';
40
+ }) => Promise<{
41
+ ok: boolean;
42
+ status: number;
43
+ statusText: string;
44
+ text(): Promise<string>;
45
+ }>;
46
+ export interface DiscoverOptions {
47
+ /**
48
+ * HTTP fetch implementation. Defaults to the ambient `fetch` global.
49
+ * Supply `undici.fetch`, a test double, or a policy-wrapping client as
50
+ * needed.
51
+ */
52
+ fetchImpl?: DiscoverFetch;
53
+ /**
54
+ * User-agent string. Precedence (highest first): this option, the
55
+ * `PEAC_USER_AGENT` environment variable, then `peac-disc`.
56
+ */
57
+ userAgent?: string;
58
+ /** Caller-supplied abort signal. */
59
+ signal?: AbortSignal;
60
+ /**
61
+ * Millisecond timeout. Ignored when `signal` is supplied (the caller
62
+ * owns cancellation). Defaults to 5_000 when neither is provided.
63
+ */
64
+ timeoutMs?: number;
65
+ /** Override the 256 KiB body cap from docs/specs/PEAC-TXT.md §6.1. */
66
+ maxBytes?: number;
67
+ /**
68
+ * Redirect policy. Defaults to `error` to avoid cross-origin surprise
69
+ * on a well-known discovery endpoint; set to `follow` explicitly if the
70
+ * deployment relies on server-side redirects.
71
+ */
72
+ redirect?: 'follow' | 'error' | 'manual';
73
+ }
74
+ /**
75
+ * Fetch and parse a remote peac.txt policy document. On success returns a
76
+ * `ParseResult` whose `data` is the validated `peac-policy/0.1`
77
+ * `PolicyDocument`. Legacy key-discovery lines in the fetched bytes are
78
+ * surfaced as warnings but never populate `data`.
79
+ */
80
+ export declare function discover(origin: string, options?: DiscoverOptions): Promise<import('./types.js').ParseResult>;
11
81
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG/F,eAAO,MAAM,OAAO,WAAW,CAAC;AAChC,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,eAAe,0BAA0B,CAAC;AAKvD,wBAAsB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,YAAY,EAAE,WAAW,CAAC,CAuBxF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjF;;;;;GAKG;AACH,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,SAAS,SAAS,CAAC;AAChC,eAAO,MAAM,eAAe,0BAA0B,CAAC;AACvD,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAGvC;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,KAAK,EAAE,MAAM,EACb,IAAI,CAAC,EAAE;IACL,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC1C,KACE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACzB,CAAC,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;CAC1C;AAED;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,OAAO,YAAY,EAAE,WAAW,CAAC,CAkE3C"}
package/dist/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { parsePolicyDocument, PolicyValidationError, PolicyLoadError, serializePolicyYaml } from '@peac/policy-kit';
2
+
1
3
  var __defProp = Object.defineProperty;
2
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
5
  var __esm = (fn, res) => function __init() {
@@ -11,162 +13,153 @@ var __export = (target, all) => {
11
13
  // src/parser.ts
12
14
  var parser_exports = {};
13
15
  __export(parser_exports, {
16
+ __resetLegacyWarningForTests: () => __resetLegacyWarningForTests,
14
17
  emit: () => emit,
15
18
  parse: () => parse,
16
19
  validate: () => validate
17
20
  });
18
- function parse(content, options = {}) {
19
- const maxLines = options.maxLines ?? MAX_LINES;
20
- const errors = [];
21
- const data = {};
22
- const lines = content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
23
- if (lines.length > maxLines) {
21
+ function fireLegacyWarning(field) {
22
+ if (legacyWarningFired) return;
23
+ legacyWarningFired = true;
24
+ if (typeof process !== "undefined" && typeof process.emitWarning === "function") {
25
+ process.emitWarning(
26
+ `peac.txt legacy key-discovery field "${field}" is deprecated and ignored. peac.txt is a policy-document surface (docs/specs/PEAC-TXT.md). Key resolution uses iss -> /.well-known/peac-issuer.json -> jwks_uri -> JWKS.`,
27
+ { code: "PEAC_LEGACY_PEAC_TXT_KEY_FIELD", type: "DeprecationWarning" }
28
+ );
29
+ }
30
+ }
31
+ function __resetLegacyWarningForTests() {
32
+ legacyWarningFired = false;
33
+ }
34
+ function collectLegacyWarnings(text) {
35
+ const warnings = [];
36
+ let firstField = null;
37
+ const lines = text.split(/\r?\n/);
38
+ lines.forEach((line, idx) => {
39
+ const match = line.match(/^\s*(verify|public_keys|jwks)\s*:/);
40
+ if (match) {
41
+ if (firstField === null) firstField = match[1];
42
+ warnings.push(
43
+ `Line ${idx + 1}: legacy key-discovery field "${match[1]}" ignored (peac.txt is policy-only; use peac-issuer.json for keys)`
44
+ );
45
+ }
46
+ });
47
+ return { warnings, firstField };
48
+ }
49
+ function parse(text) {
50
+ const warnings = [];
51
+ if (text.trim().length === 0) {
24
52
  return {
25
53
  valid: false,
26
- errors: [`Line limit exceeded: ${lines.length} > ${maxLines}`],
27
- lineCount: lines.length
54
+ errors: ["Empty policy document. Expected peac-policy/0.1 YAML or JSON."]
28
55
  };
29
56
  }
30
- for (const [index, line] of lines.entries()) {
31
- let matched = false;
32
- for (const [field, pattern] of Object.entries(FIELD_PATTERNS)) {
33
- const match = line.match(pattern);
34
- if (match) {
35
- matched = true;
36
- try {
37
- switch (field) {
38
- case "preferences":
39
- case "access_control":
40
- case "provenance":
41
- case "verify":
42
- data[field] = match[1].trim();
43
- break;
44
- case "receipts":
45
- data.receipts = match[1];
46
- break;
47
- case "payments":
48
- data.payments = parseArray(match[1]);
49
- break;
50
- case "public_keys":
51
- data.public_keys = parsePublicKeys(match[1]);
52
- break;
53
- }
54
- } catch (error) {
55
- errors.push(
56
- `Line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`
57
- );
58
- }
59
- break;
60
- }
57
+ const hasLegacyLines = LEGACY_KEY_LINE.test(text);
58
+ try {
59
+ const data = parsePolicyDocument(text);
60
+ if (hasLegacyLines) {
61
+ const legacy = collectLegacyWarnings(text);
62
+ warnings.push(...legacy.warnings);
63
+ if (legacy.firstField) fireLegacyWarning(legacy.firstField);
61
64
  }
62
- if (!matched) {
63
- errors.push(`Line ${index + 1}: Invalid format: ${line}`);
65
+ return {
66
+ valid: true,
67
+ data,
68
+ warnings: warnings.length > 0 ? warnings : void 0
69
+ };
70
+ } catch (firstErr) {
71
+ if (!hasLegacyLines) {
72
+ return failure(firstErr, warnings);
64
73
  }
65
- }
66
- if (!data.verify) {
67
- errors.push("Missing required field: verify");
68
- }
69
- return {
70
- valid: errors.length === 0,
71
- data: errors.length === 0 ? data : void 0,
72
- errors: errors.length > 0 ? errors : void 0,
73
- lineCount: lines.length
74
- };
75
- }
76
- function parseArray(content) {
77
- return content.split(",").map((item) => item.trim().replace(/^["']|["']$/g, "")).filter((item) => item.length > 0);
78
- }
79
- function parsePublicKeys(content) {
80
- const keyStrings = parseArray(content);
81
- const keys = [];
82
- for (const keyString of keyStrings) {
83
- const keyMatch = keyString.match(/^([^:]+):([^:]+):(.+)$/);
84
- if (!keyMatch) {
85
- throw new Error(`Invalid public key format: ${keyString}`);
74
+ const legacy = collectLegacyWarnings(text);
75
+ warnings.push(...legacy.warnings);
76
+ if (legacy.firstField) fireLegacyWarning(legacy.firstField);
77
+ const stripped = text.replace(LEGACY_KEY_FULL_LINE_GLOBAL, "");
78
+ if (stripped.trim().length === 0) {
79
+ return {
80
+ valid: false,
81
+ errors: ["Empty policy document after stripping legacy key-discovery lines."],
82
+ warnings: warnings.length > 0 ? warnings : void 0
83
+ };
84
+ }
85
+ try {
86
+ const data = parsePolicyDocument(stripped);
87
+ return {
88
+ valid: true,
89
+ data,
90
+ warnings: warnings.length > 0 ? warnings : void 0
91
+ };
92
+ } catch (retryErr) {
93
+ return failure(retryErr, warnings);
86
94
  }
87
- keys.push({
88
- kid: keyMatch[1],
89
- alg: keyMatch[2],
90
- key: keyMatch[3]
91
- });
92
95
  }
93
- return keys;
94
96
  }
95
- function assertSafeFieldValue(value, fieldName) {
96
- if (UNSAFE_FIELD_CHARS.test(value)) {
97
- throw new Error(
98
- `Invalid ${fieldName}: must not contain quotes, colons, brackets, newlines, or control characters`
99
- );
97
+ function failure(err, warnings) {
98
+ if (err instanceof PolicyValidationError || err instanceof PolicyLoadError) {
99
+ return {
100
+ valid: false,
101
+ errors: [err.message],
102
+ warnings: warnings.length > 0 ? warnings : void 0
103
+ };
100
104
  }
105
+ return {
106
+ valid: false,
107
+ errors: [err instanceof Error ? err.message : String(err)],
108
+ warnings: warnings.length > 0 ? warnings : void 0
109
+ };
101
110
  }
102
- function emit(data) {
103
- const lines = [];
104
- if (data.preferences) {
105
- lines.push(`preferences: ${data.preferences}`);
106
- }
107
- if (data.access_control) {
108
- lines.push(`access_control: ${data.access_control}`);
109
- }
110
- if (data.payments && data.payments.length > 0) {
111
- data.payments.forEach((p) => assertSafeFieldValue(p, "payment"));
112
- const paymentsStr = data.payments.map((p) => `"${p}"`).join(", ");
113
- lines.push(`payments: [${paymentsStr}]`);
114
- }
115
- if (data.provenance) {
116
- lines.push(`provenance: ${data.provenance}`);
117
- }
118
- if (data.receipts) {
119
- lines.push(`receipts: ${data.receipts}`);
120
- }
121
- if (data.verify) {
122
- lines.push(`verify: ${data.verify}`);
123
- }
124
- if (data.public_keys && data.public_keys.length > 0) {
125
- data.public_keys.forEach((k) => {
126
- assertSafeFieldValue(k.kid, "kid");
127
- assertSafeFieldValue(k.alg, "alg");
128
- assertSafeFieldValue(k.key, "key");
129
- });
130
- const keysStr = data.public_keys.map((k) => `"${k.kid}:${k.alg}:${k.key}"`).join(", ");
131
- lines.push(`public_keys: [${keysStr}]`);
132
- }
133
- if (lines.length > MAX_LINES) {
134
- throw new Error(`Generated peac.txt exceeds ${MAX_LINES} lines: ${lines.length}`);
135
- }
136
- return lines.join("\n");
111
+ function emit(doc) {
112
+ return serializePolicyYaml(doc);
137
113
  }
138
- function validate(content) {
139
- const result = parse(content);
140
- return result.valid;
114
+ function validate(text) {
115
+ return parse(text).valid;
141
116
  }
142
- var MAX_LINES, FIELD_PATTERNS, UNSAFE_FIELD_CHARS;
117
+ var LEGACY_KEY_LINE, LEGACY_KEY_FULL_LINE_GLOBAL, legacyWarningFired;
143
118
  var init_parser = __esm({
144
119
  "src/parser.ts"() {
145
- MAX_LINES = 20;
146
- FIELD_PATTERNS = {
147
- preferences: /^preferences:\s*(.+)$/,
148
- access_control: /^access_control:\s*(.+)$/,
149
- payments: /^payments:\s*\[([^\]]+)\]$/,
150
- provenance: /^provenance:\s*(.+)$/,
151
- receipts: /^receipts:\s*(required|optional)$/,
152
- verify: /^verify:\s*(.+)$/,
153
- public_keys: /^public_keys:\s*\[([^\]]+)\]$/
154
- };
155
- UNSAFE_FIELD_CHARS = /["\n\r\x00-\x1f:[\]]/;
120
+ LEGACY_KEY_LINE = /^\s*(verify|public_keys|jwks)\s*:/m;
121
+ LEGACY_KEY_FULL_LINE_GLOBAL = /^\s*(verify|public_keys|jwks)\s*:.*\r?\n?/gm;
122
+ legacyWarningFired = false;
156
123
  }
157
124
  });
158
125
 
159
126
  // src/index.ts
160
127
  init_parser();
161
- var VERSION = "0.9.15";
162
- var MAX_LINES2 = 20;
128
+ var MAX_BYTES = 262144;
163
129
  var WELL_KNOWN_PATH = "/.well-known/peac.txt";
164
- var UA = `PEAC/${VERSION} (+https://www.peacprotocol.org)`;
165
- async function discover(origin) {
130
+ var DEFAULT_TIMEOUT_MS = 5e3;
131
+ var DEFAULT_USER_AGENT = "peac-disc";
132
+ async function discover(origin, options = {}) {
133
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
134
+ if (typeof fetchImpl !== "function") {
135
+ return {
136
+ valid: false,
137
+ errors: [
138
+ "Discovery failed: no fetch implementation available (supply options.fetchImpl or provide a global fetch)"
139
+ ]
140
+ };
141
+ }
142
+ const envUa = typeof process !== "undefined" && typeof process.env === "object" ? process.env.PEAC_USER_AGENT : void 0;
143
+ const userAgent = options.userAgent ?? envUa ?? DEFAULT_USER_AGENT;
144
+ const maxBytes = options.maxBytes ?? MAX_BYTES;
145
+ const redirect = options.redirect ?? "error";
146
+ let localController;
147
+ let timer;
148
+ let signal = options.signal;
149
+ if (!signal) {
150
+ localController = new AbortController();
151
+ signal = localController.signal;
152
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
153
+ if (timeoutMs > 0 && Number.isFinite(timeoutMs)) {
154
+ timer = setTimeout(() => localController?.abort(), timeoutMs);
155
+ }
156
+ }
166
157
  try {
167
158
  const url = new URL(WELL_KNOWN_PATH, origin);
168
- const response = await fetch(url.toString(), {
169
- headers: { "User-Agent": UA }
159
+ const response = await fetchImpl(url.toString(), {
160
+ headers: { "User-Agent": userAgent },
161
+ signal,
162
+ redirect
170
163
  });
171
164
  if (!response.ok) {
172
165
  return {
@@ -175,6 +168,12 @@ async function discover(origin) {
175
168
  };
176
169
  }
177
170
  const content = await response.text();
171
+ if (content.length > maxBytes) {
172
+ return {
173
+ valid: false,
174
+ errors: [`peac.txt exceeds ${maxBytes} bytes (got ${content.length})`]
175
+ };
176
+ }
178
177
  const { parse: parse2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
179
178
  return parse2(content);
180
179
  } catch (error) {
@@ -182,9 +181,11 @@ async function discover(origin) {
182
181
  valid: false,
183
182
  errors: [`Discovery failed: ${error instanceof Error ? error.message : String(error)}`]
184
183
  };
184
+ } finally {
185
+ if (timer) clearTimeout(timer);
185
186
  }
186
187
  }
187
188
 
188
- export { MAX_LINES2 as MAX_LINES, VERSION, WELL_KNOWN_PATH, discover, emit, parse, validate };
189
+ export { DEFAULT_TIMEOUT_MS, MAX_BYTES, WELL_KNOWN_PATH, __resetLegacyWarningForTests, discover, emit, parse, validate };
189
190
  //# sourceMappingURL=index.js.map
190
191
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/parser.ts","../src/index.ts"],"names":["MAX_LINES","parse"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @peac/disc/parser - peac.txt parser with ≤20 lines enforcement\n * ABNF-compliant discovery document parsing\n */\n\nimport type { PeacDiscovery, ParseResult, PublicKeyInfo, ValidationOptions } from './types.js';\n\nconst MAX_LINES = 20;\nconst FIELD_PATTERNS = {\n preferences: /^preferences:\\s*(.+)$/,\n access_control: /^access_control:\\s*(.+)$/,\n payments: /^payments:\\s*\\[([^\\]]+)\\]$/,\n provenance: /^provenance:\\s*(.+)$/,\n receipts: /^receipts:\\s*(required|optional)$/,\n verify: /^verify:\\s*(.+)$/,\n public_keys: /^public_keys:\\s*\\[([^\\]]+)\\]$/,\n};\n\nexport function parse(content: string, options: ValidationOptions = {}): ParseResult {\n const maxLines = options.maxLines ?? MAX_LINES;\n const errors: string[] = [];\n const data: PeacDiscovery = {};\n\n const lines = content\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => l && !l.startsWith('#'));\n\n // Enforce line limit\n if (lines.length > maxLines) {\n return {\n valid: false,\n errors: [`Line limit exceeded: ${lines.length} > ${maxLines}`],\n lineCount: lines.length,\n };\n }\n\n // Parse each line\n for (const [index, line] of lines.entries()) {\n let matched = false;\n\n for (const [field, pattern] of Object.entries(FIELD_PATTERNS)) {\n const match = line.match(pattern);\n if (match) {\n matched = true;\n try {\n switch (field) {\n case 'preferences':\n case 'access_control':\n case 'provenance':\n case 'verify':\n data[field] = match[1].trim();\n break;\n case 'receipts':\n data.receipts = match[1] as 'required' | 'optional';\n break;\n case 'payments':\n data.payments = parseArray(match[1]);\n break;\n case 'public_keys':\n data.public_keys = parsePublicKeys(match[1]);\n break;\n }\n } catch (error) {\n errors.push(\n `Line ${index + 1}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n break;\n }\n }\n\n if (!matched) {\n errors.push(`Line ${index + 1}: Invalid format: ${line}`);\n }\n }\n\n // Validate required fields\n if (!data.verify) {\n errors.push('Missing required field: verify');\n }\n\n return {\n valid: errors.length === 0,\n data: errors.length === 0 ? data : undefined,\n errors: errors.length > 0 ? errors : undefined,\n lineCount: lines.length,\n };\n}\n\nfunction parseArray(content: string): string[] {\n return content\n .split(',')\n .map((item) => item.trim().replace(/^[\"']|[\"']$/g, ''))\n .filter((item) => item.length > 0);\n}\n\nfunction parsePublicKeys(content: string): PublicKeyInfo[] {\n const keyStrings = parseArray(content);\n const keys: PublicKeyInfo[] = [];\n\n for (const keyString of keyStrings) {\n const keyMatch = keyString.match(/^([^:]+):([^:]+):(.+)$/);\n if (!keyMatch) {\n throw new Error(`Invalid public key format: ${keyString}`);\n }\n\n keys.push({\n kid: keyMatch[1],\n alg: keyMatch[2],\n key: keyMatch[3],\n });\n }\n\n return keys;\n}\n\n/** Characters that break peac.txt wire format: quotes, colons, brackets, control chars */\nconst UNSAFE_FIELD_CHARS = /[\"\\n\\r\\x00-\\x1f:[\\]]/;\n\nfunction assertSafeFieldValue(value: string, fieldName: string): void {\n if (UNSAFE_FIELD_CHARS.test(value)) {\n throw new Error(\n `Invalid ${fieldName}: must not contain quotes, colons, brackets, newlines, or control characters`\n );\n }\n}\n\nexport function emit(data: PeacDiscovery): string {\n const lines: string[] = [];\n\n if (data.preferences) {\n lines.push(`preferences: ${data.preferences}`);\n }\n\n if (data.access_control) {\n lines.push(`access_control: ${data.access_control}`);\n }\n\n if (data.payments && data.payments.length > 0) {\n data.payments.forEach((p) => assertSafeFieldValue(p, 'payment'));\n const paymentsStr = data.payments.map((p) => `\"${p}\"`).join(', ');\n lines.push(`payments: [${paymentsStr}]`);\n }\n\n if (data.provenance) {\n lines.push(`provenance: ${data.provenance}`);\n }\n\n if (data.receipts) {\n lines.push(`receipts: ${data.receipts}`);\n }\n\n if (data.verify) {\n lines.push(`verify: ${data.verify}`);\n }\n\n if (data.public_keys && data.public_keys.length > 0) {\n data.public_keys.forEach((k) => {\n assertSafeFieldValue(k.kid, 'kid');\n assertSafeFieldValue(k.alg, 'alg');\n assertSafeFieldValue(k.key, 'key');\n });\n const keysStr = data.public_keys.map((k) => `\"${k.kid}:${k.alg}:${k.key}\"`).join(', ');\n lines.push(`public_keys: [${keysStr}]`);\n }\n\n // Enforce line limit during emission\n if (lines.length > MAX_LINES) {\n throw new Error(`Generated peac.txt exceeds ${MAX_LINES} lines: ${lines.length}`);\n }\n\n return lines.join('\\n');\n}\n\nexport function validate(content: string): boolean {\n const result = parse(content);\n return result.valid;\n}\n","/**\n * @peac/disc - PEAC discovery with ≤20 lines enforcement\n * ABNF-compliant .well-known/peac.txt parser and generator\n */\n\nexport { parse, emit, validate } from './parser.js';\nexport type { PeacDiscovery, PublicKeyInfo, ParseResult, ValidationOptions } from './types.js';\n\n// Constants\nexport const VERSION = '0.9.15';\nexport const MAX_LINES = 20;\nexport const WELL_KNOWN_PATH = '/.well-known/peac.txt';\n\nconst UA = `PEAC/${VERSION} (+https://www.peacprotocol.org)`;\n\n// Convenience function for fetching and parsing discovery documents\nexport async function discover(origin: string): Promise<import('./types.js').ParseResult> {\n try {\n const url = new URL(WELL_KNOWN_PATH, origin);\n const response = await fetch(url.toString(), {\n headers: { 'User-Agent': UA },\n });\n\n if (!response.ok) {\n return {\n valid: false,\n errors: [`HTTP ${response.status}: ${response.statusText}`],\n };\n }\n\n const content = await response.text();\n const { parse } = await import('./parser.js');\n return parse(content);\n } catch (error) {\n return {\n valid: false,\n errors: [`Discovery failed: ${error instanceof Error ? error.message : String(error)}`],\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/parser.ts","../src/index.ts"],"names":["parse"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * @peac/disc/parser - thin peac.txt policy-document loader/validator.\n *\n * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md.\n * Full parsing is delegated to `@peac/policy-kit.parsePolicyDocument`;\n * this module only provides:\n *\n * - format detection (YAML vs JSON) per PEAC-TXT.md §5.1\n * - a tolerant `parse()` wrapper that returns a structured `ParseResult`\n * (rather than throwing)\n * - structured warnings for legacy key-discovery lines (`verify`,\n * `public_keys`, `jwks`) that appeared in pre-v0.12.14 peac.txt\n * examples. Those lines are NEVER honored here: key discovery flows\n * through `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS\n * (docs/specs/PEAC-ISSUER.md).\n * - a tiny `emit()` helper that serializes a `PolicyDocument` via\n * `@peac/policy-kit.serializePolicyYaml`\n *\n * @see docs/specs/PEAC-TXT.md\n * @see docs/specs/PEAC-ISSUER.md\n */\n\nimport {\n PolicyLoadError,\n PolicyValidationError,\n parsePolicyDocument,\n serializePolicyYaml,\n type PolicyDocument,\n} from '@peac/policy-kit';\nimport type { ParseResult } from './types.js';\n\nconst LEGACY_KEY_LINE = /^\\s*(verify|public_keys|jwks)\\s*:/m;\n/** Strips the whole line (including the trailing newline) when matched. */\nconst LEGACY_KEY_FULL_LINE_GLOBAL = /^\\s*(verify|public_keys|jwks)\\s*:.*\\r?\\n?/gm;\n\nlet legacyWarningFired = false;\n\nfunction fireLegacyWarning(field: string): void {\n if (legacyWarningFired) return;\n legacyWarningFired = true;\n if (typeof process !== 'undefined' && typeof process.emitWarning === 'function') {\n process.emitWarning(\n `peac.txt legacy key-discovery field \"${field}\" is deprecated and ignored. ` +\n `peac.txt is a policy-document surface (docs/specs/PEAC-TXT.md). ` +\n `Key resolution uses iss -> /.well-known/peac-issuer.json -> jwks_uri -> JWKS.`,\n { code: 'PEAC_LEGACY_PEAC_TXT_KEY_FIELD', type: 'DeprecationWarning' }\n );\n }\n}\n\n/**\n * Reset the one-shot legacy-warning flag. Exposed for tests that need to\n * observe the warning more than once per process.\n */\nexport function __resetLegacyWarningForTests(): void {\n legacyWarningFired = false;\n}\n\nfunction collectLegacyWarnings(text: string): { warnings: string[]; firstField: string | null } {\n const warnings: string[] = [];\n let firstField: string | null = null;\n const lines = text.split(/\\r?\\n/);\n lines.forEach((line, idx) => {\n const match = line.match(/^\\s*(verify|public_keys|jwks)\\s*:/);\n if (match) {\n if (firstField === null) firstField = match[1];\n warnings.push(\n `Line ${idx + 1}: legacy key-discovery field \"${match[1]}\" ignored ` +\n `(peac.txt is policy-only; use peac-issuer.json for keys)`\n );\n }\n });\n return { warnings, firstField };\n}\n\n/**\n * Parse a peac.txt policy document. Accepts YAML or JSON per\n * `docs/specs/PEAC-TXT.md` §5.1. On success, `data` is the validated\n * `peac-policy/0.1` `PolicyDocument`.\n *\n * Legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`) are\n * tolerated via a two-pass strategy: first the raw bytes are handed to\n * `parsePolicyDocument`; if validation fails AND top-level legacy lines\n * are present, the legacy lines are stripped and parsing is retried\n * once. Detected legacy lines are listed in `warnings` and surface a\n * structured `PEAC_LEGACY_PEAC_TXT_KEY_FIELD` `DeprecationWarning` once\n * per process. They never populate the parsed result. This preserves\n * the original bytes when a policy document happens to mention those\n * tokens inside comments, block scalars, or rule text.\n */\nexport function parse(text: string): ParseResult {\n const warnings: string[] = [];\n\n if (text.trim().length === 0) {\n return {\n valid: false,\n errors: ['Empty policy document. Expected peac-policy/0.1 YAML or JSON.'],\n };\n }\n\n const hasLegacyLines = LEGACY_KEY_LINE.test(text);\n\n // First pass: try the raw bytes. If they parse cleanly, legacy-looking\n // substrings inside block scalars / comments / rule text are not\n // mutated.\n try {\n const data = parsePolicyDocument(text);\n if (hasLegacyLines) {\n const legacy = collectLegacyWarnings(text);\n warnings.push(...legacy.warnings);\n if (legacy.firstField) fireLegacyWarning(legacy.firstField);\n }\n return {\n valid: true,\n data,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (firstErr) {\n if (!hasLegacyLines) {\n return failure(firstErr, warnings);\n }\n // Second pass: strip top-level legacy key-discovery lines and retry.\n const legacy = collectLegacyWarnings(text);\n warnings.push(...legacy.warnings);\n if (legacy.firstField) fireLegacyWarning(legacy.firstField);\n\n const stripped = text.replace(LEGACY_KEY_FULL_LINE_GLOBAL, '');\n if (stripped.trim().length === 0) {\n return {\n valid: false,\n errors: ['Empty policy document after stripping legacy key-discovery lines.'],\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n try {\n const data = parsePolicyDocument(stripped);\n return {\n valid: true,\n data,\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n } catch (retryErr) {\n return failure(retryErr, warnings);\n }\n }\n}\n\nfunction failure(err: unknown, warnings: string[]): ParseResult {\n if (err instanceof PolicyValidationError || err instanceof PolicyLoadError) {\n return {\n valid: false,\n errors: [err.message],\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n }\n return {\n valid: false,\n errors: [err instanceof Error ? err.message : String(err)],\n warnings: warnings.length > 0 ? warnings : undefined,\n };\n}\n\n/**\n * Serialize a `peac-policy/0.1` `PolicyDocument` as YAML suitable for\n * serving at `/.well-known/peac.txt`. Delegates to\n * `@peac/policy-kit.serializePolicyYaml`.\n */\nexport function emit(doc: PolicyDocument): string {\n return serializePolicyYaml(doc);\n}\n\n/**\n * Convenience predicate: returns `true` iff `text` parses as a valid\n * `peac-policy/0.1` document.\n */\nexport function validate(text: string): boolean {\n return parse(text).valid;\n}\n","/**\n * @peac/disc - thin peac.txt policy-document loader/validator and remote fetcher.\n *\n * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md. Full\n * parsing is delegated to `@peac/policy-kit.parsePolicyDocument`; this\n * package provides a tolerant `parse()` wrapper, a `discover()` remote\n * fetcher, and structured warnings for legacy key-discovery lines that\n * appeared in older peac.txt examples.\n *\n * `peac.txt` is NOT a key discovery surface. Cryptographic key resolution\n * flows through `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS\n * (docs/specs/PEAC-ISSUER.md). Callers that need key material MUST use\n * `parseIssuerConfig` / `fetchIssuerConfig` from `@peac/protocol`.\n *\n * Legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`) are\n * tolerated on parse: they are stripped before validation, surfaced on\n * `ParseResult.warnings`, and fire a structured `process.emitWarning`\n * with code `PEAC_LEGACY_PEAC_TXT_KEY_FIELD` once per process.\n */\n\nexport { parse, emit, validate, __resetLegacyWarningForTests } from './parser.js';\nexport type { ParseResult, ValidationOptions, PolicyDocument } from './types.js';\n\n/**\n * @deprecated Retained for one minor to keep existing import paths\n * compiling. peac.txt policy documents now resolve to a `PolicyDocument`\n * (re-exported from `@peac/policy-kit`). Removal target: next cleanup\n * release.\n */\nexport type { PeacDiscovery, PublicKeyInfo } from './types.js';\n\nexport const MAX_BYTES = 262144; // 256 KiB, per docs/specs/PEAC-TXT.md §6.1\nexport const WELL_KNOWN_PATH = '/.well-known/peac.txt';\nexport const DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_USER_AGENT = 'peac-disc';\n\n/**\n * Minimal fetch signature accepted by `discover`. `undici` / `node-fetch` /\n * browser / test-double implementations all satisfy this.\n */\nexport type DiscoverFetch = (\n input: string,\n init?: {\n headers?: Record<string, string>;\n signal?: AbortSignal;\n redirect?: 'follow' | 'error' | 'manual';\n }\n) => Promise<{\n ok: boolean;\n status: number;\n statusText: string;\n text(): Promise<string>;\n}>;\n\nexport interface DiscoverOptions {\n /**\n * HTTP fetch implementation. Defaults to the ambient `fetch` global.\n * Supply `undici.fetch`, a test double, or a policy-wrapping client as\n * needed.\n */\n fetchImpl?: DiscoverFetch;\n /**\n * User-agent string. Precedence (highest first): this option, the\n * `PEAC_USER_AGENT` environment variable, then `peac-disc`.\n */\n userAgent?: string;\n /** Caller-supplied abort signal. */\n signal?: AbortSignal;\n /**\n * Millisecond timeout. Ignored when `signal` is supplied (the caller\n * owns cancellation). Defaults to 5_000 when neither is provided.\n */\n timeoutMs?: number;\n /** Override the 256 KiB body cap from docs/specs/PEAC-TXT.md §6.1. */\n maxBytes?: number;\n /**\n * Redirect policy. Defaults to `error` to avoid cross-origin surprise\n * on a well-known discovery endpoint; set to `follow` explicitly if the\n * deployment relies on server-side redirects.\n */\n redirect?: 'follow' | 'error' | 'manual';\n}\n\n/**\n * Fetch and parse a remote peac.txt policy document. On success returns a\n * `ParseResult` whose `data` is the validated `peac-policy/0.1`\n * `PolicyDocument`. Legacy key-discovery lines in the fetched bytes are\n * surfaced as warnings but never populate `data`.\n */\nexport async function discover(\n origin: string,\n options: DiscoverOptions = {}\n): Promise<import('./types.js').ParseResult> {\n const fetchImpl = (options.fetchImpl ?? (globalThis as { fetch?: DiscoverFetch }).fetch) as\n | DiscoverFetch\n | undefined;\n if (typeof fetchImpl !== 'function') {\n return {\n valid: false,\n errors: [\n 'Discovery failed: no fetch implementation available (supply options.fetchImpl or provide a global fetch)',\n ],\n };\n }\n\n const envUa =\n typeof process !== 'undefined' && typeof process.env === 'object'\n ? process.env.PEAC_USER_AGENT\n : undefined;\n const userAgent = options.userAgent ?? envUa ?? DEFAULT_USER_AGENT;\n const maxBytes = options.maxBytes ?? MAX_BYTES;\n const redirect = options.redirect ?? 'error';\n\n // If the caller did not supply an AbortSignal, install a local one driven by timeoutMs.\n let localController: AbortController | undefined;\n let timer: ReturnType<typeof setTimeout> | undefined;\n let signal = options.signal;\n if (!signal) {\n localController = new AbortController();\n signal = localController.signal;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n if (timeoutMs > 0 && Number.isFinite(timeoutMs)) {\n timer = setTimeout(() => localController?.abort(), timeoutMs);\n }\n }\n\n try {\n const url = new URL(WELL_KNOWN_PATH, origin);\n const response = await fetchImpl(url.toString(), {\n headers: { 'User-Agent': userAgent },\n signal,\n redirect,\n });\n\n if (!response.ok) {\n return {\n valid: false,\n errors: [`HTTP ${response.status}: ${response.statusText}`],\n };\n }\n\n const content = await response.text();\n if (content.length > maxBytes) {\n return {\n valid: false,\n errors: [`peac.txt exceeds ${maxBytes} bytes (got ${content.length})`],\n };\n }\n const { parse } = await import('./parser.js');\n return parse(content);\n } catch (error) {\n return {\n valid: false,\n errors: [`Discovery failed: ${error instanceof Error ? error.message : String(error)}`],\n };\n } finally {\n if (timer) clearTimeout(timer);\n }\n}\n"]}
package/dist/parser.d.ts CHANGED
@@ -1,9 +1,56 @@
1
1
  /**
2
- * @peac/disc/parser - peac.txt parser with ≤20 lines enforcement
3
- * ABNF-compliant discovery document parsing
2
+ * @peac/disc/parser - thin peac.txt policy-document loader/validator.
3
+ *
4
+ * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md.
5
+ * Full parsing is delegated to `@peac/policy-kit.parsePolicyDocument`;
6
+ * this module only provides:
7
+ *
8
+ * - format detection (YAML vs JSON) per PEAC-TXT.md §5.1
9
+ * - a tolerant `parse()` wrapper that returns a structured `ParseResult`
10
+ * (rather than throwing)
11
+ * - structured warnings for legacy key-discovery lines (`verify`,
12
+ * `public_keys`, `jwks`) that appeared in pre-v0.12.14 peac.txt
13
+ * examples. Those lines are NEVER honored here: key discovery flows
14
+ * through `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS
15
+ * (docs/specs/PEAC-ISSUER.md).
16
+ * - a tiny `emit()` helper that serializes a `PolicyDocument` via
17
+ * `@peac/policy-kit.serializePolicyYaml`
18
+ *
19
+ * @see docs/specs/PEAC-TXT.md
20
+ * @see docs/specs/PEAC-ISSUER.md
4
21
  */
5
- import type { PeacDiscovery, ParseResult, ValidationOptions } from './types.js';
6
- export declare function parse(content: string, options?: ValidationOptions): ParseResult;
7
- export declare function emit(data: PeacDiscovery): string;
8
- export declare function validate(content: string): boolean;
22
+ import { type PolicyDocument } from '@peac/policy-kit';
23
+ import type { ParseResult } from './types.js';
24
+ /**
25
+ * Reset the one-shot legacy-warning flag. Exposed for tests that need to
26
+ * observe the warning more than once per process.
27
+ */
28
+ export declare function __resetLegacyWarningForTests(): void;
29
+ /**
30
+ * Parse a peac.txt policy document. Accepts YAML or JSON per
31
+ * `docs/specs/PEAC-TXT.md` §5.1. On success, `data` is the validated
32
+ * `peac-policy/0.1` `PolicyDocument`.
33
+ *
34
+ * Legacy key-discovery lines (`verify:`, `public_keys:`, `jwks:`) are
35
+ * tolerated via a two-pass strategy: first the raw bytes are handed to
36
+ * `parsePolicyDocument`; if validation fails AND top-level legacy lines
37
+ * are present, the legacy lines are stripped and parsing is retried
38
+ * once. Detected legacy lines are listed in `warnings` and surface a
39
+ * structured `PEAC_LEGACY_PEAC_TXT_KEY_FIELD` `DeprecationWarning` once
40
+ * per process. They never populate the parsed result. This preserves
41
+ * the original bytes when a policy document happens to mention those
42
+ * tokens inside comments, block scalars, or rule text.
43
+ */
44
+ export declare function parse(text: string): ParseResult;
45
+ /**
46
+ * Serialize a `peac-policy/0.1` `PolicyDocument` as YAML suitable for
47
+ * serving at `/.well-known/peac.txt`. Delegates to
48
+ * `@peac/policy-kit.serializePolicyYaml`.
49
+ */
50
+ export declare function emit(doc: PolicyDocument): string;
51
+ /**
52
+ * Convenience predicate: returns `true` iff `text` parses as a valid
53
+ * `peac-policy/0.1` document.
54
+ */
55
+ export declare function validate(text: string): boolean;
9
56
  //# sourceMappingURL=parser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAiB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAa/F,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,WAAW,CAsEnF;AAwCD,wBAAgB,IAAI,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CA6ChD;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGjD"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAqB9C;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD;AAmBD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAuD/C;AAiBD;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAEhD;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE9C"}
package/dist/types.d.ts CHANGED
@@ -1,28 +1,57 @@
1
1
  /**
2
- * @peac/disc/types - Discovery types for .well-known/peac.txt
2
+ * @peac/disc/types - Discovery result types for .well-known/peac.txt
3
+ *
4
+ * peac.txt is a POLICY DOCUMENT surface per docs/specs/PEAC-TXT.md.
5
+ * It is NOT a key discovery surface. Key resolution uses the normative
6
+ * chain: `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` -> JWKS.
7
+ *
8
+ * `@peac/disc` is a thin loader/validator over peac-policy/0.1 bytes
9
+ * (YAML or JSON). Full parsing is delegated to
10
+ * `@peac/policy-kit.parsePolicyDocument`; the canonical `PolicyDocument`
11
+ * type is re-exported from `@peac/policy-kit`.
12
+ *
13
+ * @see docs/specs/PEAC-TXT.md
14
+ * @see docs/specs/PEAC-ISSUER.md
3
15
  */
4
- export interface PeacDiscovery {
5
- preferences?: string;
6
- access_control?: string;
7
- payments?: string[];
8
- provenance?: string;
9
- receipts?: 'required' | 'optional';
10
- verify?: string;
11
- public_keys?: PublicKeyInfo[];
16
+ import type { PolicyDocument } from '@peac/policy-kit';
17
+ export type { PolicyDocument };
18
+ /**
19
+ * Result of `parse()`. On success, `data` is the validated
20
+ * `peac-policy/0.1` `PolicyDocument`. On failure, `errors` explains why.
21
+ * `warnings` carries non-fatal advisories; in particular, legacy
22
+ * key-discovery lines (`verify`, `public_keys`, `jwks`) that appeared in
23
+ * older peac.txt examples are listed here and also fire a structured
24
+ * `process.emitWarning` with code `PEAC_LEGACY_PEAC_TXT_KEY_FIELD`
25
+ * once per process.
26
+ */
27
+ export interface ParseResult {
28
+ valid: boolean;
29
+ data?: PolicyDocument;
30
+ errors?: string[];
31
+ warnings?: string[];
32
+ }
33
+ export interface ValidationOptions {
34
+ /** Soft line cap for advisory purposes (default 100, per PEAC-TXT.md §6.2). */
35
+ recommendedMaxLines?: number;
12
36
  }
37
+ /**
38
+ * @deprecated Key discovery via peac.txt is retired. Use the normative
39
+ * discovery chain `iss` -> /.well-known/peac-issuer.json -> `jwks_uri` ->
40
+ * JWKS instead. This type is retained for one minor to keep existing import
41
+ * paths compiling. Removal target: next cleanup release.
42
+ */
13
43
  export interface PublicKeyInfo {
14
44
  kid: string;
15
45
  alg: string;
16
46
  key: string;
17
47
  }
18
- export interface ParseResult {
19
- valid: boolean;
20
- data?: PeacDiscovery;
21
- errors?: string[];
22
- lineCount?: number;
23
- }
24
- export interface ValidationOptions {
25
- maxLines?: number;
26
- strictAbnf?: boolean;
48
+ /**
49
+ * @deprecated pre-v0.12.14 alias for the legacy line-based PEAC discovery
50
+ * shape. Use the `ParseResult.data` (`PolicyDocument`) returned by `parse()`.
51
+ * Retained for one minor so existing import paths keep compiling; removal
52
+ * target: next cleanup release.
53
+ */
54
+ export interface PeacDiscovery {
55
+ [key: string]: unknown;
27
56
  }
28
57
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC;IACnC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,aAAa,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,YAAY,EAAE,cAAc,EAAE,CAAC;AAE/B;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@peac/disc",
3
- "version": "0.12.13",
4
- "description": "PEAC discovery with ≤20 lines enforcement",
3
+ "version": "0.12.14",
4
+ "description": "Thin loader / validator and remote fetcher for peac.txt policy documents (peac-policy/0.1; docs/specs/PEAC-TXT.md)",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
7
7
  "types": "dist/index.d.ts",
@@ -20,7 +20,9 @@
20
20
  "README.md",
21
21
  "LICENSE"
22
22
  ],
23
- "dependencies": {},
23
+ "dependencies": {
24
+ "@peac/policy-kit": "0.12.14"
25
+ },
24
26
  "devDependencies": {
25
27
  "typescript": "^5.0.0",
26
28
  "tsup": "^8.0.0"