proofscan 0.10.2 → 0.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.ja.md +272 -95
  2. package/README.md +200 -311
  3. package/dist/cli.js +4 -2
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/index.d.ts +1 -0
  6. package/dist/commands/index.d.ts.map +1 -1
  7. package/dist/commands/index.js +2 -0
  8. package/dist/commands/index.js.map +1 -1
  9. package/dist/commands/popl.d.ts +16 -0
  10. package/dist/commands/popl.d.ts.map +1 -0
  11. package/dist/commands/popl.js +495 -0
  12. package/dist/commands/popl.js.map +1 -0
  13. package/dist/popl/artifacts.d.ts +78 -0
  14. package/dist/popl/artifacts.d.ts.map +1 -0
  15. package/dist/popl/artifacts.js +205 -0
  16. package/dist/popl/artifacts.js.map +1 -0
  17. package/dist/popl/index.d.ts +10 -0
  18. package/dist/popl/index.d.ts.map +1 -0
  19. package/dist/popl/index.js +14 -0
  20. package/dist/popl/index.js.map +1 -0
  21. package/dist/popl/sanitizer.d.ts +86 -0
  22. package/dist/popl/sanitizer.d.ts.map +1 -0
  23. package/dist/popl/sanitizer.js +271 -0
  24. package/dist/popl/sanitizer.js.map +1 -0
  25. package/dist/popl/service.d.ts +46 -0
  26. package/dist/popl/service.d.ts.map +1 -0
  27. package/dist/popl/service.js +231 -0
  28. package/dist/popl/service.js.map +1 -0
  29. package/dist/popl/types.d.ts +195 -0
  30. package/dist/popl/types.d.ts.map +1 -0
  31. package/dist/popl/types.js +20 -0
  32. package/dist/popl/types.js.map +1 -0
  33. package/dist/shell/popl-commands.d.ts +26 -0
  34. package/dist/shell/popl-commands.d.ts.map +1 -0
  35. package/dist/shell/popl-commands.js +281 -0
  36. package/dist/shell/popl-commands.js.map +1 -0
  37. package/dist/shell/repl.d.ts.map +1 -1
  38. package/dist/shell/repl.js +6 -0
  39. package/dist/shell/repl.js.map +1 -1
  40. package/package.json +6 -4
@@ -0,0 +1,271 @@
1
+ /**
2
+ * POPL Sanitizer (Phase 6.0)
3
+ *
4
+ * Sanitization ruleset v1 for public disclosure safety.
5
+ *
6
+ * Rules:
7
+ * 1. Path removal - Windows and POSIX absolute paths
8
+ * 2. Secret token removal - Authorization, Bearer, api_key, token, secret
9
+ * 3. RPC payload handling - Replace values with hashes, keep key structure
10
+ */
11
+ import { createHash } from 'crypto';
12
+ /** Current sanitization ruleset version */
13
+ export const SANITIZER_RULESET_VERSION = 1;
14
+ /** Maximum string length to process with regex (ReDoS prevention) */
15
+ const MAX_REGEX_INPUT_LENGTH = 1000;
16
+ /** Redacted placeholder for paths */
17
+ const REDACTED_PATH = '<redacted:path>';
18
+ /** Redacted placeholder for secrets */
19
+ const REDACTED_SECRET = '<redacted:secret>';
20
+ /** Redacted placeholder for values (RPC payloads) */
21
+ const REDACTED_VALUE = '<redacted:value>';
22
+ /**
23
+ * Patterns for detecting absolute paths
24
+ */
25
+ const PATH_PATTERNS = [
26
+ // Windows: C:\Users\... or D:\...
27
+ /^[A-Za-z]:\\[^\s"']+/,
28
+ // Windows: \\server\share
29
+ /^\\\\[^\s"']+/,
30
+ // POSIX: /home/... /Users/... /var/... etc.
31
+ /^\/(?:home|Users|var|tmp|etc|opt|usr|root|mnt|media|srv|private)[^\s"']*/,
32
+ // Generic POSIX paths starting with / followed by word chars
33
+ /^\/[a-zA-Z0-9_-]+(?:\/[^\s"']*)?/,
34
+ ];
35
+ /**
36
+ * Patterns for detecting secret-like keys
37
+ */
38
+ const SECRET_KEY_PATTERNS = [
39
+ /^api[_-]?key$/i,
40
+ /^auth(?:orization)?$/i,
41
+ /^bearer$/i,
42
+ /^token$/i,
43
+ /^secret$/i,
44
+ /^password$/i,
45
+ /^passwd$/i,
46
+ /^credential/i,
47
+ /^private[_-]?key$/i,
48
+ /^access[_-]?token$/i,
49
+ /^refresh[_-]?token$/i,
50
+ /^session[_-]?(?:id|token)$/i,
51
+ /^cookie$/i,
52
+ /^x-api-key$/i,
53
+ /^x-auth/i,
54
+ ];
55
+ /**
56
+ * Patterns for detecting secret-like values
57
+ */
58
+ const SECRET_VALUE_PATTERNS = [
59
+ // Bearer tokens
60
+ /^Bearer\s+[A-Za-z0-9._-]+/i,
61
+ // Authorization header
62
+ /^Basic\s+[A-Za-z0-9+/=]+/i,
63
+ // JWT-like tokens (three base64 sections)
64
+ /^eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/,
65
+ // API keys (long alphanumeric strings)
66
+ /^[a-zA-Z0-9_-]{32,}$/,
67
+ // Hedera keys
68
+ /^302[a-fA-F0-9]{64,}/,
69
+ // secret:// references (not already masked)
70
+ /^secret:\/\/(?!\*\*\*$)/,
71
+ // dpapi: references
72
+ /^dpapi:[a-zA-Z0-9_-]+$/,
73
+ ];
74
+ /**
75
+ * Check if a string looks like an absolute path
76
+ * Includes length check to prevent ReDoS attacks
77
+ */
78
+ function isAbsolutePath(value) {
79
+ // Skip long strings to prevent ReDoS
80
+ if (value.length > MAX_REGEX_INPUT_LENGTH) {
81
+ return false;
82
+ }
83
+ return PATH_PATTERNS.some((pattern) => pattern.test(value));
84
+ }
85
+ /**
86
+ * Check if a key name suggests it contains a secret
87
+ * Includes length check to prevent ReDoS attacks
88
+ */
89
+ function isSecretKey(key) {
90
+ // Skip long strings to prevent ReDoS
91
+ if (key.length > MAX_REGEX_INPUT_LENGTH) {
92
+ return false;
93
+ }
94
+ return SECRET_KEY_PATTERNS.some((pattern) => pattern.test(key));
95
+ }
96
+ /**
97
+ * Check if a value looks like a secret
98
+ * Includes length check to prevent ReDoS attacks
99
+ */
100
+ function isSecretValue(value) {
101
+ // Skip long strings to prevent ReDoS
102
+ if (value.length > MAX_REGEX_INPUT_LENGTH) {
103
+ return false;
104
+ }
105
+ return SECRET_VALUE_PATTERNS.some((pattern) => pattern.test(value));
106
+ }
107
+ /**
108
+ * Compute SHA-256 hash of a value (first 16 chars)
109
+ */
110
+ export function hashValue(value) {
111
+ const str = typeof value === 'string' ? value : JSON.stringify(value);
112
+ const hash = createHash('sha256').update(str, 'utf8').digest('hex');
113
+ return hash.slice(0, 16);
114
+ }
115
+ /**
116
+ * Sanitize a JSON-like value for public disclosure.
117
+ *
118
+ * @param value - Any JSON-serializable value
119
+ * @param options - Sanitization options
120
+ * @returns Sanitized value and statistics
121
+ */
122
+ export function sanitize(value, options = {}) {
123
+ let redactedCount = 0;
124
+ const redactedCategories = new Set();
125
+ function process(val, key) {
126
+ // Null/undefined pass through
127
+ if (val === null || val === undefined) {
128
+ return val;
129
+ }
130
+ // String processing
131
+ if (typeof val === 'string') {
132
+ // Check for paths
133
+ if (isAbsolutePath(val)) {
134
+ redactedCount++;
135
+ redactedCategories.add('path');
136
+ return REDACTED_PATH;
137
+ }
138
+ // Check for secret values
139
+ if (isSecretValue(val)) {
140
+ redactedCount++;
141
+ redactedCategories.add('secret');
142
+ return REDACTED_SECRET;
143
+ }
144
+ // Check if key suggests secret
145
+ if (key && isSecretKey(key) && val.length > 0) {
146
+ redactedCount++;
147
+ redactedCategories.add('secret');
148
+ return REDACTED_SECRET;
149
+ }
150
+ return val;
151
+ }
152
+ // Array processing
153
+ if (Array.isArray(val)) {
154
+ return val.map((item, i) => process(item, String(i)));
155
+ }
156
+ // Object processing
157
+ if (typeof val === 'object') {
158
+ const result = {};
159
+ for (const [k, v] of Object.entries(val)) {
160
+ result[k] = process(v, k);
161
+ }
162
+ return result;
163
+ }
164
+ // Primitives (number, boolean) pass through
165
+ return val;
166
+ }
167
+ const sanitized = process(value, options.context?.key);
168
+ return { value: sanitized, redactedCount, redactedCategories };
169
+ }
170
+ /**
171
+ * Sanitize RPC payload for public disclosure.
172
+ *
173
+ * This is more aggressive than general sanitization:
174
+ * - Replaces all argument values with hashes
175
+ * - Keeps key structure for auditability
176
+ * - Stores original hash for verification
177
+ *
178
+ * @param payload - RPC arguments or result
179
+ * @returns Sanitized structure with hashes
180
+ */
181
+ export function sanitizeRpcPayload(payload) {
182
+ if (payload === null || payload === undefined) {
183
+ return {
184
+ sanitized: null,
185
+ payload_sha256: hashValue(null),
186
+ keys: [],
187
+ };
188
+ }
189
+ // Get original hash before any processing
190
+ const payload_sha256 = hashValue(payload);
191
+ // Extract keys
192
+ const keys = Object.keys(payload);
193
+ // Create sanitized version with value hashes
194
+ const sanitized = {};
195
+ for (const [key, value] of Object.entries(payload)) {
196
+ sanitized[key] = {
197
+ _type: typeof value,
198
+ _hash: hashValue(value),
199
+ };
200
+ }
201
+ return { sanitized, payload_sha256, keys };
202
+ }
203
+ /**
204
+ * Sanitize a log line for public disclosure.
205
+ *
206
+ * @param line - Log line object
207
+ * @returns Sanitized log line
208
+ */
209
+ export function sanitizeLogLine(line) {
210
+ const result = sanitize(line);
211
+ return result.value;
212
+ }
213
+ /**
214
+ * Sanitize RPC event for public disclosure.
215
+ *
216
+ * @param event - RPC event object from events.db
217
+ * @returns Sanitized event
218
+ */
219
+ export function sanitizeRpcEvent(event) {
220
+ // Basic fields (safe to include)
221
+ const sanitized = {
222
+ event_id: event.event_id,
223
+ session_id: event.session_id,
224
+ rpc_id: event.rpc_id,
225
+ direction: event.direction,
226
+ kind: event.kind,
227
+ ts: event.ts,
228
+ seq: event.seq,
229
+ summary: event.summary ? sanitize(event.summary).value : null,
230
+ payload_hash: event.payload_hash,
231
+ };
232
+ // Process raw_json if present
233
+ if (event.raw_json) {
234
+ try {
235
+ const parsed = JSON.parse(event.raw_json);
236
+ // For request/response, sanitize params/result
237
+ if (parsed.params) {
238
+ const { sanitized: sanParams, payload_sha256, keys } = sanitizeRpcPayload(parsed.params);
239
+ sanitized.params_keys = keys;
240
+ sanitized.params_sha256 = payload_sha256;
241
+ // Don't include sanitized params - just keys and hash
242
+ }
243
+ if (parsed.result !== undefined) {
244
+ const resultHash = hashValue(parsed.result);
245
+ sanitized.result_sha256 = resultHash;
246
+ sanitized.result_type = typeof parsed.result;
247
+ }
248
+ if (parsed.error) {
249
+ // Error codes/messages are generally safe
250
+ sanitized.error_code = parsed.error.code;
251
+ sanitized.error_message = sanitize(parsed.error.message).value;
252
+ }
253
+ // Method name is safe
254
+ if (parsed.method) {
255
+ sanitized.method = parsed.method;
256
+ }
257
+ }
258
+ catch {
259
+ // If parsing fails, just note that
260
+ sanitized.raw_json_parse_error = true;
261
+ }
262
+ }
263
+ return sanitized;
264
+ }
265
+ /**
266
+ * Compute SHA-256 hash of file contents
267
+ */
268
+ export function hashFileContent(content) {
269
+ return createHash('sha256').update(content).digest('hex');
270
+ }
271
+ //# sourceMappingURL=sanitizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitizer.js","sourceRoot":"","sources":["../../src/popl/sanitizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * POPL Service Layer (Phase 6.0)
3
+ *
4
+ * Core service for POPL entry generation.
5
+ * Shared by CLI and shell - neither knows about @references.
6
+ */
7
+ import { type PoplDocument, type PoplConfig, type CreatePoplOptions, type CreatePoplResult } from './types.js';
8
+ /**
9
+ * Check if .popl directory exists
10
+ */
11
+ export declare function hasPoplDir(root: string): boolean;
12
+ /**
13
+ * Get path to .popl directory
14
+ */
15
+ export declare function getPoplDir(root: string): string;
16
+ /**
17
+ * Get path to popl_entries directory
18
+ */
19
+ export declare function getPoplEntriesDir(root: string): string;
20
+ /**
21
+ * Initialize .popl directory structure
22
+ */
23
+ export declare function initPoplDir(root: string): Promise<void>;
24
+ /**
25
+ * Load POPL config from .popl/config.json
26
+ * Returns empty config with warning on parse error.
27
+ */
28
+ export declare function loadPoplConfig(root: string): Promise<PoplConfig>;
29
+ /**
30
+ * Create a POPL entry for a session
31
+ *
32
+ * This is the core service function called by both CLI and shell.
33
+ */
34
+ export declare function createSessionPoplEntry(sessionId: string, configDir: string, options: Omit<CreatePoplOptions, 'kind' | 'ids'>): Promise<CreatePoplResult>;
35
+ /**
36
+ * List existing POPL entries
37
+ */
38
+ export declare function listPoplEntries(root: string): Promise<{
39
+ id: string;
40
+ path: string;
41
+ }[]>;
42
+ /**
43
+ * Read a POPL entry document
44
+ */
45
+ export declare function readPoplEntry(entryPath: string): Promise<PoplDocument | null>;
46
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/popl/service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAGL,KAAK,YAAY,EAEjB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EAGtB,MAAM,YAAY,CAAC;AAapB;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkB7D;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAiBtE;AA8BD;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,KAAK,CAAC,GAC/C,OAAO,CAAC,gBAAgB,CAAC,CA2G3B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,CAgBzC;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAanF"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * POPL Service Layer (Phase 6.0)
3
+ *
4
+ * Core service for POPL entry generation.
5
+ * Shared by CLI and shell - neither knows about @references.
6
+ */
7
+ import { mkdir, writeFile, readFile } from 'fs/promises';
8
+ import { existsSync } from 'fs';
9
+ import { join, relative, isAbsolute } from 'path';
10
+ import { ulid } from 'ulid';
11
+ import * as yaml from 'yaml';
12
+ import { POPL_VERSION, TRUST_LABELS, } from './types.js';
13
+ import { generateSessionArtifacts } from './artifacts.js';
14
+ import { SANITIZER_RULESET_VERSION } from './sanitizer.js';
15
+ /** POPL directory name */
16
+ const POPL_DIR = '.popl';
17
+ /** POPL entries subdirectory */
18
+ const POPL_ENTRIES_DIR = 'popl_entries';
19
+ /** POPL config filename */
20
+ const POPL_CONFIG_FILE = 'config.json';
21
+ /**
22
+ * Check if .popl directory exists
23
+ */
24
+ export function hasPoplDir(root) {
25
+ return existsSync(join(root, POPL_DIR));
26
+ }
27
+ /**
28
+ * Get path to .popl directory
29
+ */
30
+ export function getPoplDir(root) {
31
+ return join(root, POPL_DIR);
32
+ }
33
+ /**
34
+ * Get path to popl_entries directory
35
+ */
36
+ export function getPoplEntriesDir(root) {
37
+ return join(root, POPL_DIR, POPL_ENTRIES_DIR);
38
+ }
39
+ /**
40
+ * Initialize .popl directory structure
41
+ */
42
+ export async function initPoplDir(root) {
43
+ const poplDir = getPoplDir(root);
44
+ const entriesDir = getPoplEntriesDir(root);
45
+ // Create directories
46
+ await mkdir(entriesDir, { recursive: true });
47
+ // Create default config if not exists
48
+ const configPath = join(poplDir, POPL_CONFIG_FILE);
49
+ if (!existsSync(configPath)) {
50
+ const defaultConfig = {
51
+ author: {
52
+ name: 'Unknown',
53
+ },
54
+ redaction: 'default',
55
+ };
56
+ await writeFile(configPath, JSON.stringify(defaultConfig, null, 2), 'utf-8');
57
+ }
58
+ }
59
+ /**
60
+ * Load POPL config from .popl/config.json
61
+ * Returns empty config with warning on parse error.
62
+ */
63
+ export async function loadPoplConfig(root) {
64
+ const configPath = join(getPoplDir(root), POPL_CONFIG_FILE);
65
+ if (!existsSync(configPath)) {
66
+ return {};
67
+ }
68
+ try {
69
+ const content = await readFile(configPath, 'utf-8');
70
+ return JSON.parse(content);
71
+ }
72
+ catch (error) {
73
+ // Log warning for invalid config (don't fail silently)
74
+ console.warn(`Warning: Failed to parse .popl/config.json: ${error instanceof Error ? error.message : String(error)}`);
75
+ return {};
76
+ }
77
+ }
78
+ /**
79
+ * Convert absolute path to relative path for POPL output
80
+ * Ensures no absolute paths leak into POPL.yml
81
+ */
82
+ function toRelativePath(absolutePath, baseDir) {
83
+ if (!isAbsolute(absolutePath)) {
84
+ return absolutePath;
85
+ }
86
+ return relative(baseDir, absolutePath);
87
+ }
88
+ /**
89
+ * Generate default title for a POPL entry
90
+ */
91
+ function generateDefaultTitle(kind, connectorId, timestamp) {
92
+ const dateStr = timestamp.toISOString().slice(0, 19).replace('T', ' ');
93
+ const kindLabel = kind.charAt(0).toUpperCase() + kind.slice(1);
94
+ if (connectorId) {
95
+ return `MCP ${kindLabel} POPL Entry ${connectorId} ${dateStr}`;
96
+ }
97
+ return `MCP ${kindLabel} POPL Entry ${dateStr}`;
98
+ }
99
+ /**
100
+ * Create a POPL entry for a session
101
+ *
102
+ * This is the core service function called by both CLI and shell.
103
+ */
104
+ export async function createSessionPoplEntry(sessionId, configDir, options) {
105
+ const { outputRoot, title, author, unsafeIncludeRaw = false } = options;
106
+ // Validate .popl exists
107
+ if (!hasPoplDir(outputRoot)) {
108
+ return {
109
+ success: false,
110
+ error: '.popl directory not found. Run "pfscan popl init" first.',
111
+ };
112
+ }
113
+ try {
114
+ // Generate artifacts and get session info
115
+ const { artifacts, session, summary } = await generateSessionArtifacts(sessionId, configDir);
116
+ // Generate entry ID
117
+ const entryId = ulid();
118
+ // Create entry directory
119
+ const entryPath = join(getPoplEntriesDir(outputRoot), entryId);
120
+ await mkdir(entryPath, { recursive: true });
121
+ // Write artifacts
122
+ const artifactList = [artifacts.status, artifacts.rpc, artifacts.validation];
123
+ if (artifacts.logs) {
124
+ artifactList.push(artifacts.logs);
125
+ }
126
+ for (const artifact of artifactList) {
127
+ const artifactPath = join(entryPath, artifact.artifact.path);
128
+ await writeFile(artifactPath, artifact.content, 'utf-8');
129
+ }
130
+ // Load config for author
131
+ const config = await loadPoplConfig(outputRoot);
132
+ const effectiveAuthor = author || config.author || { name: 'Unknown' };
133
+ // Generate title
134
+ const createdAt = new Date();
135
+ const effectiveTitle = title || generateDefaultTitle('session', session.connector_id, createdAt);
136
+ // Build POPL document
137
+ const poplDoc = {
138
+ popl: POPL_VERSION,
139
+ entry: {
140
+ id: entryId,
141
+ created_at: createdAt.toISOString(),
142
+ title: effectiveTitle,
143
+ author: effectiveAuthor,
144
+ trust: {
145
+ level: 0,
146
+ label: TRUST_LABELS[0],
147
+ },
148
+ },
149
+ target: {
150
+ kind: 'session',
151
+ name: 'session',
152
+ ids: {
153
+ connector_id: session.connector_id,
154
+ session_id: session.session_id,
155
+ },
156
+ },
157
+ capture: {
158
+ window: {
159
+ started_at: session.started_at,
160
+ ended_at: session.ended_at || createdAt.toISOString(),
161
+ },
162
+ summary,
163
+ mcp: {
164
+ servers: [
165
+ {
166
+ name: session.connector_id,
167
+ },
168
+ ],
169
+ },
170
+ },
171
+ evidence: {
172
+ policy: {
173
+ redaction: unsafeIncludeRaw ? 'none' : 'default',
174
+ ruleset_version: SANITIZER_RULESET_VERSION,
175
+ },
176
+ artifacts: artifactList.map((a) => a.artifact),
177
+ },
178
+ };
179
+ // Write POPL.yml
180
+ const poplYmlPath = join(entryPath, 'POPL.yml');
181
+ const poplYmlContent = yaml.stringify(poplDoc);
182
+ await writeFile(poplYmlPath, poplYmlContent, 'utf-8');
183
+ // Return relative paths for display (avoid leaking absolute paths)
184
+ return {
185
+ success: true,
186
+ entryId,
187
+ entryPath: toRelativePath(entryPath, outputRoot),
188
+ poplYmlPath: toRelativePath(poplYmlPath, outputRoot),
189
+ };
190
+ }
191
+ catch (error) {
192
+ return {
193
+ success: false,
194
+ error: error instanceof Error ? error.message : String(error),
195
+ };
196
+ }
197
+ }
198
+ /**
199
+ * List existing POPL entries
200
+ */
201
+ export async function listPoplEntries(root) {
202
+ const entriesDir = getPoplEntriesDir(root);
203
+ if (!existsSync(entriesDir)) {
204
+ return [];
205
+ }
206
+ const { readdir } = await import('fs/promises');
207
+ const entries = await readdir(entriesDir, { withFileTypes: true });
208
+ return entries
209
+ .filter((e) => e.isDirectory())
210
+ .map((e) => ({
211
+ id: e.name,
212
+ path: join(entriesDir, e.name),
213
+ }));
214
+ }
215
+ /**
216
+ * Read a POPL entry document
217
+ */
218
+ export async function readPoplEntry(entryPath) {
219
+ const poplYmlPath = join(entryPath, 'POPL.yml');
220
+ if (!existsSync(poplYmlPath)) {
221
+ return null;
222
+ }
223
+ try {
224
+ const content = await readFile(poplYmlPath, 'utf-8');
225
+ return yaml.parse(content);
226
+ }
227
+ catch {
228
+ return null;
229
+ }
230
+ }
231
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"","sources":["../../src/popl/service.ts"],"names":[],"mappings":"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"}