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.
- package/README.ja.md +272 -95
- package/README.md +200 -311
- package/dist/cli.js +4 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +2 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/popl.d.ts +16 -0
- package/dist/commands/popl.d.ts.map +1 -0
- package/dist/commands/popl.js +495 -0
- package/dist/commands/popl.js.map +1 -0
- package/dist/popl/artifacts.d.ts +78 -0
- package/dist/popl/artifacts.d.ts.map +1 -0
- package/dist/popl/artifacts.js +205 -0
- package/dist/popl/artifacts.js.map +1 -0
- package/dist/popl/index.d.ts +10 -0
- package/dist/popl/index.d.ts.map +1 -0
- package/dist/popl/index.js +14 -0
- package/dist/popl/index.js.map +1 -0
- package/dist/popl/sanitizer.d.ts +86 -0
- package/dist/popl/sanitizer.d.ts.map +1 -0
- package/dist/popl/sanitizer.js +271 -0
- package/dist/popl/sanitizer.js.map +1 -0
- package/dist/popl/service.d.ts +46 -0
- package/dist/popl/service.d.ts.map +1 -0
- package/dist/popl/service.js +231 -0
- package/dist/popl/service.js.map +1 -0
- package/dist/popl/types.d.ts +195 -0
- package/dist/popl/types.d.ts.map +1 -0
- package/dist/popl/types.js +20 -0
- package/dist/popl/types.js.map +1 -0
- package/dist/shell/popl-commands.d.ts +26 -0
- package/dist/shell/popl-commands.d.ts.map +1 -0
- package/dist/shell/popl-commands.js +281 -0
- package/dist/shell/popl-commands.js.map +1 -0
- package/dist/shell/repl.d.ts.map +1 -1
- package/dist/shell/repl.js +6 -0
- package/dist/shell/repl.js.map +1 -1
- 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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"}
|