@runcore-sh/runcore 0.1.8 → 0.1.10
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/dist/access/manifest.d.ts +59 -0
- package/dist/access/manifest.d.ts.map +1 -0
- package/dist/access/manifest.js +251 -0
- package/dist/access/manifest.js.map +1 -0
- package/dist/activity/log.d.ts +1 -1
- package/dist/activity/log.d.ts.map +1 -1
- package/dist/agents/autonomous.d.ts.map +1 -1
- package/dist/agents/autonomous.js +38 -0
- package/dist/agents/autonomous.js.map +1 -1
- package/dist/agents/governance.d.ts +70 -0
- package/dist/agents/governance.d.ts.map +1 -0
- package/dist/agents/governance.js +220 -0
- package/dist/agents/governance.js.map +1 -0
- package/dist/agents/governed-spawn.d.ts +83 -0
- package/dist/agents/governed-spawn.d.ts.map +1 -0
- package/dist/agents/governed-spawn.js +186 -0
- package/dist/agents/governed-spawn.js.map +1 -0
- package/dist/agents/heartbeat.d.ts +91 -0
- package/dist/agents/heartbeat.d.ts.map +1 -0
- package/dist/agents/heartbeat.js +323 -0
- package/dist/agents/heartbeat.js.map +1 -0
- package/dist/agents/index.d.ts +4 -1
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +6 -1
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/spawn-policy.d.ts +45 -0
- package/dist/agents/spawn-policy.d.ts.map +1 -0
- package/dist/agents/spawn-policy.js +202 -0
- package/dist/agents/spawn-policy.js.map +1 -0
- package/dist/alert.d.ts +16 -0
- package/dist/alert.d.ts.map +1 -0
- package/dist/alert.js +70 -0
- package/dist/alert.js.map +1 -0
- package/dist/cli.js +261 -32
- package/dist/cli.js.map +1 -1
- package/dist/credentials/store.d.ts +1 -1
- package/dist/credentials/store.d.ts.map +1 -1
- package/dist/credentials/store.js +14 -3
- package/dist/credentials/store.js.map +1 -1
- package/dist/crystallizer.d.ts +56 -0
- package/dist/crystallizer.d.ts.map +1 -0
- package/dist/crystallizer.js +159 -0
- package/dist/crystallizer.js.map +1 -0
- package/dist/distiller.d.ts +48 -0
- package/dist/distiller.d.ts.map +1 -0
- package/dist/distiller.js +140 -0
- package/dist/distiller.js.map +1 -0
- package/dist/files/deep-index.d.ts +59 -0
- package/dist/files/deep-index.d.ts.map +1 -0
- package/dist/files/deep-index.js +337 -0
- package/dist/files/deep-index.js.map +1 -0
- package/dist/files/import.d.ts +44 -0
- package/dist/files/import.d.ts.map +1 -0
- package/dist/files/import.js +213 -0
- package/dist/files/import.js.map +1 -0
- package/dist/files/index-local.d.ts +37 -0
- package/dist/files/index-local.d.ts.map +1 -0
- package/dist/files/index-local.js +198 -0
- package/dist/files/index-local.js.map +1 -0
- package/dist/google/auth.d.ts +2 -0
- package/dist/google/auth.d.ts.map +1 -1
- package/dist/google/auth.js +2 -0
- package/dist/google/auth.js.map +1 -1
- package/dist/integrations/gate.d.ts +40 -0
- package/dist/integrations/gate.d.ts.map +1 -0
- package/dist/integrations/gate.js +100 -0
- package/dist/integrations/gate.js.map +1 -0
- package/dist/lib/audit.d.ts +43 -0
- package/dist/lib/audit.d.ts.map +1 -0
- package/dist/lib/audit.js +120 -0
- package/dist/lib/audit.js.map +1 -0
- package/dist/lib/brain-io.d.ts.map +1 -1
- package/dist/lib/brain-io.js +52 -0
- package/dist/lib/brain-io.js.map +1 -1
- package/dist/lib/dpapi.d.ts +14 -0
- package/dist/lib/dpapi.d.ts.map +1 -0
- package/dist/lib/dpapi.js +104 -0
- package/dist/lib/dpapi.js.map +1 -0
- package/dist/lib/glob-match.d.ts +22 -0
- package/dist/lib/glob-match.d.ts.map +1 -0
- package/dist/lib/glob-match.js +64 -0
- package/dist/lib/glob-match.js.map +1 -0
- package/dist/lib/locked.d.ts +40 -0
- package/dist/lib/locked.d.ts.map +1 -0
- package/dist/lib/locked.js +130 -0
- package/dist/lib/locked.js.map +1 -0
- package/dist/llm/complete.d.ts.map +1 -1
- package/dist/llm/complete.js +5 -2
- package/dist/llm/complete.js.map +1 -1
- package/dist/llm/fetch-guard.d.ts +16 -0
- package/dist/llm/fetch-guard.d.ts.map +1 -0
- package/dist/llm/fetch-guard.js +61 -0
- package/dist/llm/fetch-guard.js.map +1 -0
- package/dist/llm/guard.d.ts +40 -0
- package/dist/llm/guard.d.ts.map +1 -0
- package/dist/llm/guard.js +88 -0
- package/dist/llm/guard.js.map +1 -0
- package/dist/llm/membrane.d.ts +46 -0
- package/dist/llm/membrane.d.ts.map +1 -0
- package/dist/llm/membrane.js +123 -0
- package/dist/llm/membrane.js.map +1 -0
- package/dist/llm/providers/index.d.ts +5 -1
- package/dist/llm/providers/index.d.ts.map +1 -1
- package/dist/llm/providers/index.js +8 -1
- package/dist/llm/providers/index.js.map +1 -1
- package/dist/llm/redact.d.ts +39 -0
- package/dist/llm/redact.d.ts.map +1 -0
- package/dist/llm/redact.js +155 -0
- package/dist/llm/redact.js.map +1 -0
- package/dist/llm/sensitive-registry.d.ts +33 -0
- package/dist/llm/sensitive-registry.d.ts.map +1 -0
- package/dist/llm/sensitive-registry.js +106 -0
- package/dist/llm/sensitive-registry.js.map +1 -0
- package/dist/mcp-server.d.ts +11 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +520 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/mdns.d.ts +17 -0
- package/dist/mdns.d.ts.map +1 -0
- package/dist/mdns.js +110 -0
- package/dist/mdns.js.map +1 -0
- package/dist/nerve/push.d.ts +26 -0
- package/dist/nerve/push.d.ts.map +1 -0
- package/dist/nerve/push.js +170 -0
- package/dist/nerve/push.js.map +1 -0
- package/dist/nerve/state.d.ts +35 -0
- package/dist/nerve/state.d.ts.map +1 -0
- package/dist/nerve/state.js +257 -0
- package/dist/nerve/state.js.map +1 -0
- package/dist/posture/engine.d.ts +41 -0
- package/dist/posture/engine.d.ts.map +1 -0
- package/dist/posture/engine.js +217 -0
- package/dist/posture/engine.js.map +1 -0
- package/dist/posture/index.d.ts +11 -0
- package/dist/posture/index.d.ts.map +1 -0
- package/dist/posture/index.js +10 -0
- package/dist/posture/index.js.map +1 -0
- package/dist/posture/middleware.d.ts +30 -0
- package/dist/posture/middleware.d.ts.map +1 -0
- package/dist/posture/middleware.js +92 -0
- package/dist/posture/middleware.js.map +1 -0
- package/dist/posture/types.d.ts +61 -0
- package/dist/posture/types.d.ts.map +1 -0
- package/dist/posture/types.js +48 -0
- package/dist/posture/types.js.map +1 -0
- package/dist/resend/inbox.d.ts +23 -0
- package/dist/resend/inbox.d.ts.map +1 -0
- package/dist/resend/inbox.js +198 -0
- package/dist/resend/inbox.js.map +1 -0
- package/dist/resend/webhooks.d.ts +30 -0
- package/dist/resend/webhooks.d.ts.map +1 -0
- package/dist/resend/webhooks.js +244 -0
- package/dist/resend/webhooks.js.map +1 -0
- package/dist/server.d.ts +5 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +773 -58
- package/dist/server.js.map +1 -1
- package/dist/settings.d.ts +14 -1
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +32 -1
- package/dist/settings.js.map +1 -1
- package/dist/tier/bond.d.ts +51 -0
- package/dist/tier/bond.d.ts.map +1 -0
- package/dist/tier/bond.js +154 -0
- package/dist/tier/bond.js.map +1 -0
- package/dist/tier/freeze.d.ts +21 -0
- package/dist/tier/freeze.d.ts.map +1 -0
- package/dist/tier/freeze.js +73 -0
- package/dist/tier/freeze.js.map +1 -0
- package/dist/tier/gate.d.ts +11 -0
- package/dist/tier/gate.d.ts.map +1 -0
- package/dist/tier/gate.js +25 -0
- package/dist/tier/gate.js.map +1 -0
- package/dist/tier/heartbeat.d.ts +22 -0
- package/dist/tier/heartbeat.d.ts.map +1 -0
- package/dist/tier/heartbeat.js +128 -0
- package/dist/tier/heartbeat.js.map +1 -0
- package/dist/tier/token.d.ts +22 -0
- package/dist/tier/token.d.ts.map +1 -0
- package/dist/tier/token.js +100 -0
- package/dist/tier/token.js.map +1 -0
- package/dist/tier/types.d.ts +44 -0
- package/dist/tier/types.d.ts.map +1 -0
- package/dist/tier/types.js +61 -0
- package/dist/tier/types.js.map +1 -0
- package/dist/updater.d.ts +32 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +145 -0
- package/dist/updater.js.map +1 -0
- package/dist/vault/policy.d.ts +42 -0
- package/dist/vault/policy.d.ts.map +1 -0
- package/dist/vault/policy.js +159 -0
- package/dist/vault/policy.js.map +1 -0
- package/dist/vault/store.d.ts +6 -0
- package/dist/vault/store.d.ts.map +1 -1
- package/dist/vault/store.js +15 -5
- package/dist/vault/store.js.map +1 -1
- package/dist/vault/transfer.d.ts +33 -0
- package/dist/vault/transfer.d.ts.map +1 -0
- package/dist/vault/transfer.js +187 -0
- package/dist/vault/transfer.js.map +1 -0
- package/dist/voucher.d.ts +39 -0
- package/dist/voucher.d.ts.map +1 -0
- package/dist/voucher.js +105 -0
- package/dist/voucher.js.map +1 -0
- package/dist/webhooks/handlers.d.ts +10 -0
- package/dist/webhooks/handlers.d.ts.map +1 -1
- package/dist/webhooks/handlers.js +53 -0
- package/dist/webhooks/handlers.js.map +1 -1
- package/dist/webhooks/index.d.ts +2 -2
- package/dist/webhooks/index.d.ts.map +1 -1
- package/dist/webhooks/index.js +2 -2
- package/dist/webhooks/index.js.map +1 -1
- package/dist/webhooks/verify.d.ts +8 -0
- package/dist/webhooks/verify.d.ts.map +1 -1
- package/dist/webhooks/verify.js +56 -0
- package/dist/webhooks/verify.js.map +1 -1
- package/package.json +8 -2
- package/public/board.html +8 -3
- package/public/browser.html +8 -3
- package/public/library.html +8 -3
- package/public/observatory.html +8 -3
- package/public/ops.html +8 -3
- package/public/registry.html +627 -0
- package/public/roadmap.html +975 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit logging for brain file access.
|
|
3
|
+
* Appends access records to brain/ops/audit.jsonl.
|
|
4
|
+
* Uses AsyncLocalStorage to track caller identity (MCP tool, HTTP route, etc.).
|
|
5
|
+
*
|
|
6
|
+
* Fire-and-forget — audit failures never block or crash the caller.
|
|
7
|
+
*/
|
|
8
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
|
+
import { appendFile } from "node:fs/promises";
|
|
10
|
+
import { appendFileSync, mkdirSync, existsSync } from "node:fs";
|
|
11
|
+
import { join, relative } from "node:path";
|
|
12
|
+
import { createLogger } from "../utils/logger.js";
|
|
13
|
+
const log = createLogger("audit");
|
|
14
|
+
// ── Caller context via AsyncLocalStorage ─────────────────────────────────────
|
|
15
|
+
const auditContextStore = new AsyncLocalStorage();
|
|
16
|
+
/**
|
|
17
|
+
* Run a function with audit context. All brain file reads within the callback
|
|
18
|
+
* will be tagged with the given caller and channel.
|
|
19
|
+
*/
|
|
20
|
+
export function runWithAuditContext(ctx, fn) {
|
|
21
|
+
return auditContextStore.run(ctx, fn);
|
|
22
|
+
}
|
|
23
|
+
/** Get the current audit context (if set). */
|
|
24
|
+
export function getAuditContext() {
|
|
25
|
+
return auditContextStore.getStore();
|
|
26
|
+
}
|
|
27
|
+
// ── File setup ───────────────────────────────────────────────────────────────
|
|
28
|
+
const BRAIN_DIR = join(process.cwd(), "brain");
|
|
29
|
+
const OPS_DIR = join(BRAIN_DIR, "ops");
|
|
30
|
+
const AUDIT_FILE = join(OPS_DIR, "audit.jsonl");
|
|
31
|
+
const SCHEMA_LINE = JSON.stringify({
|
|
32
|
+
_schema: "audit",
|
|
33
|
+
_version: "1.0",
|
|
34
|
+
_fields: "timestamp,file,method,caller,channel",
|
|
35
|
+
});
|
|
36
|
+
let fileEnsured = false;
|
|
37
|
+
function ensureFile() {
|
|
38
|
+
if (fileEnsured)
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
if (!existsSync(OPS_DIR)) {
|
|
42
|
+
mkdirSync(OPS_DIR, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
if (!existsSync(AUDIT_FILE)) {
|
|
45
|
+
appendFileSync(AUDIT_FILE, SCHEMA_LINE + "\n", "utf-8");
|
|
46
|
+
}
|
|
47
|
+
fileEnsured = true;
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
log.debug(`Failed to ensure audit file: ${err instanceof Error ? err.message : String(err)}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ── Core logging ─────────────────────────────────────────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* Resolve a full path to a relative brain path for cleaner logs.
|
|
56
|
+
* Returns the path as-is if it's not under brain/.
|
|
57
|
+
*/
|
|
58
|
+
function toBrainRelative(filePath) {
|
|
59
|
+
try {
|
|
60
|
+
const rel = relative(BRAIN_DIR, filePath);
|
|
61
|
+
// If the relative path escapes brain/, return the original
|
|
62
|
+
if (rel.startsWith("..") || rel.startsWith("/"))
|
|
63
|
+
return filePath;
|
|
64
|
+
return rel.replace(/\\/g, "/");
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return filePath;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Log a brain file read. Fire-and-forget (async).
|
|
72
|
+
* Skips logging reads of the audit file itself to avoid recursion.
|
|
73
|
+
*/
|
|
74
|
+
export function logAccess(filePath, method) {
|
|
75
|
+
// Prevent recursive audit of the audit file
|
|
76
|
+
if (filePath === AUDIT_FILE)
|
|
77
|
+
return;
|
|
78
|
+
const ctx = auditContextStore.getStore();
|
|
79
|
+
const entry = {
|
|
80
|
+
timestamp: new Date().toISOString(),
|
|
81
|
+
file: toBrainRelative(filePath),
|
|
82
|
+
method,
|
|
83
|
+
caller: ctx?.caller,
|
|
84
|
+
channel: ctx?.channel,
|
|
85
|
+
};
|
|
86
|
+
try {
|
|
87
|
+
ensureFile();
|
|
88
|
+
const line = JSON.stringify(entry);
|
|
89
|
+
// Async append — fire-and-forget
|
|
90
|
+
appendFile(AUDIT_FILE, line + "\n", "utf-8").catch((err) => {
|
|
91
|
+
log.debug(`Audit write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
log.debug(`Audit log error: ${err instanceof Error ? err.message : String(err)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Synchronous variant for use in readBrainLinesSync.
|
|
100
|
+
*/
|
|
101
|
+
export function logAccessSync(filePath, method) {
|
|
102
|
+
if (filePath === AUDIT_FILE)
|
|
103
|
+
return;
|
|
104
|
+
const ctx = auditContextStore.getStore();
|
|
105
|
+
const entry = {
|
|
106
|
+
timestamp: new Date().toISOString(),
|
|
107
|
+
file: toBrainRelative(filePath),
|
|
108
|
+
method,
|
|
109
|
+
caller: ctx?.caller,
|
|
110
|
+
channel: ctx?.channel,
|
|
111
|
+
};
|
|
112
|
+
try {
|
|
113
|
+
ensureFile();
|
|
114
|
+
appendFileSync(AUDIT_FILE, JSON.stringify(entry) + "\n", "utf-8");
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
log.debug(`Audit sync write failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../src/lib/audit.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brain-io.d.ts","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"brain-io.d.ts","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA+EH;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA0BxE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMvF;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ1F;AAID;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUrE;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOrF;AAID;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA0B7D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAM5E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAInD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAO9E;AAID;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1F"}
|
package/dist/lib/brain-io.js
CHANGED
|
@@ -16,6 +16,10 @@ import { readFileSync, appendFileSync, mkdirSync, existsSync, } from "node:fs";
|
|
|
16
16
|
import { dirname } from "node:path";
|
|
17
17
|
import { createLogger } from "../utils/logger.js";
|
|
18
18
|
import { getEncryptionKey, getWriteEncryptionKey } from "./key-store.js";
|
|
19
|
+
import { logAccess, logAccessSync } from "./audit.js";
|
|
20
|
+
import { assertNotLocked, toBrainRelativePath } from "./locked.js";
|
|
21
|
+
import { getAuditContext } from "./audit.js";
|
|
22
|
+
import { getManifest, canRead, canWrite } from "../access/manifest.js";
|
|
19
23
|
const log = createLogger("brain-io");
|
|
20
24
|
import { shouldEncryptFile } from "./encryption-config.js";
|
|
21
25
|
import { encryptLine, decryptLine, isEncryptedLine, encryptFile, decryptFile, isEncryptedFile, } from "./encryption.js";
|
|
@@ -32,6 +36,37 @@ function writeKey(filePath) {
|
|
|
32
36
|
return null;
|
|
33
37
|
return getWriteEncryptionKey();
|
|
34
38
|
}
|
|
39
|
+
// ── Access enforcement ───────────────────────────────────────────────────────
|
|
40
|
+
/**
|
|
41
|
+
* Assert that the current instance (from AuditContext) has access to the path.
|
|
42
|
+
* No-op when instanceName is undefined (backward compatible).
|
|
43
|
+
* Checks the instance's access manifest; logs denied access to audit.
|
|
44
|
+
*
|
|
45
|
+
* @param absolutePath - Absolute file path
|
|
46
|
+
* @param operation - "read" or "write"
|
|
47
|
+
*/
|
|
48
|
+
function assertAccess(absolutePath, operation) {
|
|
49
|
+
const ctx = getAuditContext();
|
|
50
|
+
if (!ctx?.instanceName)
|
|
51
|
+
return; // No instance context — skip check
|
|
52
|
+
const relPath = toBrainRelativePath(absolutePath);
|
|
53
|
+
if (relPath === null)
|
|
54
|
+
return; // Not a brain path
|
|
55
|
+
const manifest = getManifest(ctx.instanceName);
|
|
56
|
+
if (!manifest)
|
|
57
|
+
return; // No manifest loaded — skip (permissive for unknown instances)
|
|
58
|
+
const allowed = operation === "read"
|
|
59
|
+
? canRead(manifest, relPath)
|
|
60
|
+
: canWrite(manifest, relPath);
|
|
61
|
+
if (!allowed) {
|
|
62
|
+
log.warn("Access denied by manifest", {
|
|
63
|
+
instance: ctx.instanceName,
|
|
64
|
+
path: relPath,
|
|
65
|
+
operation,
|
|
66
|
+
});
|
|
67
|
+
throw new Error(`Access denied: ${ctx.instanceName} cannot ${operation} ${relPath}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
35
70
|
// ── Async JSONL (per-line) I/O ───────────────────────────────────────────────
|
|
36
71
|
/**
|
|
37
72
|
* Read a JSONL file, decrypting each line if needed.
|
|
@@ -39,6 +74,9 @@ function writeKey(filePath) {
|
|
|
39
74
|
* Empty/whitespace lines are filtered out.
|
|
40
75
|
*/
|
|
41
76
|
export async function readBrainLines(filePath) {
|
|
77
|
+
assertNotLocked(filePath);
|
|
78
|
+
assertAccess(filePath, "read");
|
|
79
|
+
logAccess(filePath, "readBrainLines");
|
|
42
80
|
let raw;
|
|
43
81
|
try {
|
|
44
82
|
raw = await readFile(filePath, "utf-8");
|
|
@@ -68,6 +106,8 @@ export async function readBrainLines(filePath) {
|
|
|
68
106
|
* The line should be a JSON string (not newline-terminated).
|
|
69
107
|
*/
|
|
70
108
|
export async function appendBrainLine(filePath, jsonLine) {
|
|
109
|
+
assertNotLocked(filePath);
|
|
110
|
+
assertAccess(filePath, "write");
|
|
71
111
|
const key = writeKey(filePath);
|
|
72
112
|
const line = key ? encryptLine(jsonLine, key) : jsonLine;
|
|
73
113
|
await appendFile(filePath, line + "\n", "utf-8");
|
|
@@ -77,6 +117,8 @@ export async function appendBrainLine(filePath, jsonLine) {
|
|
|
77
117
|
* Used for compaction/rotation where the whole file is rewritten.
|
|
78
118
|
*/
|
|
79
119
|
export async function writeBrainLines(filePath, jsonLines) {
|
|
120
|
+
assertNotLocked(filePath);
|
|
121
|
+
assertAccess(filePath, "write");
|
|
80
122
|
const key = writeKey(filePath);
|
|
81
123
|
const output = jsonLines
|
|
82
124
|
.map((l) => (key ? encryptLine(l, key) : l))
|
|
@@ -89,6 +131,9 @@ export async function writeBrainLines(filePath, jsonLines) {
|
|
|
89
131
|
* Returns the plaintext content. Falls back to raw content if not encrypted.
|
|
90
132
|
*/
|
|
91
133
|
export async function readBrainFile(filePath) {
|
|
134
|
+
assertNotLocked(filePath);
|
|
135
|
+
assertAccess(filePath, "read");
|
|
136
|
+
logAccess(filePath, "readBrainFile");
|
|
92
137
|
const raw = await readFile(filePath, "utf-8");
|
|
93
138
|
const key = readKey(filePath);
|
|
94
139
|
if (key && isEncryptedFile(raw)) {
|
|
@@ -101,6 +146,8 @@ export async function readBrainFile(filePath) {
|
|
|
101
146
|
* Creates parent directories if needed.
|
|
102
147
|
*/
|
|
103
148
|
export async function writeBrainFile(filePath, content) {
|
|
149
|
+
assertNotLocked(filePath);
|
|
150
|
+
assertAccess(filePath, "write");
|
|
104
151
|
await mkdir(dirname(filePath), { recursive: true });
|
|
105
152
|
const key = writeKey(filePath);
|
|
106
153
|
const output = key ? encryptFile(content, key) : content;
|
|
@@ -111,6 +158,9 @@ export async function writeBrainFile(filePath, content) {
|
|
|
111
158
|
* Synchronously read a JSONL file, decrypting each line if needed.
|
|
112
159
|
*/
|
|
113
160
|
export function readBrainLinesSync(filePath) {
|
|
161
|
+
assertNotLocked(filePath);
|
|
162
|
+
assertAccess(filePath, "read");
|
|
163
|
+
logAccessSync(filePath, "readBrainLinesSync");
|
|
114
164
|
let raw;
|
|
115
165
|
try {
|
|
116
166
|
raw = readFileSync(filePath, "utf-8");
|
|
@@ -139,6 +189,8 @@ export function readBrainLinesSync(filePath) {
|
|
|
139
189
|
* Synchronously append a single line to a JSONL file, encrypting if enabled.
|
|
140
190
|
*/
|
|
141
191
|
export function appendBrainLineSync(filePath, jsonLine) {
|
|
192
|
+
assertNotLocked(filePath);
|
|
193
|
+
assertAccess(filePath, "write");
|
|
142
194
|
const key = writeKey(filePath);
|
|
143
195
|
const line = key ? encryptLine(jsonLine, key) : jsonLine;
|
|
144
196
|
appendFileSync(filePath, line + "\n", "utf-8");
|
package/dist/lib/brain-io.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brain-io.js","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EACL,YAAY,EAEZ,cAAc,EACd,SAAS,EACT,UAAU,GACX,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"brain-io.js","sourceRoot":"","sources":["../../src/lib/brain-io.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DPAPI wrapper — encrypts/decrypts data using Windows Data Protection API.
|
|
3
|
+
* Keys are tied to the current Windows user account.
|
|
4
|
+
* Falls back to plaintext on non-Windows or if DPAPI is unavailable.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Read a session key file. Tries DPAPI-protected format first (.dpapi),
|
|
8
|
+
* falls back to plaintext hex. If plaintext found, migrates to DPAPI.
|
|
9
|
+
* Returns the raw key as a Buffer, or null if not found.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readSessionKey(keyPath: string): Promise<Buffer | null>;
|
|
12
|
+
/** Check if DPAPI is available on this system. */
|
|
13
|
+
export declare function isDpapiAvailable(): boolean;
|
|
14
|
+
//# sourceMappingURL=dpapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpapi.d.ts","sourceRoot":"","sources":["../../src/lib/dpapi.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkDH;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuC5E;AAED,kDAAkD;AAClD,wBAAgB,gBAAgB,IAAI,OAAO,CAQ1C"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DPAPI wrapper — encrypts/decrypts data using Windows Data Protection API.
|
|
3
|
+
* Keys are tied to the current Windows user account.
|
|
4
|
+
* Falls back to plaintext on non-Windows or if DPAPI is unavailable.
|
|
5
|
+
*/
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
import { readFile, writeFile, realpath } from "node:fs/promises";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
const IS_WINDOWS = process.platform === "win32";
|
|
10
|
+
/** Encode a PowerShell script as base64 UTF-16LE for -EncodedCommand. */
|
|
11
|
+
function encodePS(script) {
|
|
12
|
+
return Buffer.from(script, "utf16le").toString("base64");
|
|
13
|
+
}
|
|
14
|
+
/** Run a PowerShell script reliably via -EncodedCommand. */
|
|
15
|
+
function runPS(script) {
|
|
16
|
+
const encoded = encodePS(script);
|
|
17
|
+
return execSync(`powershell -NoProfile -EncodedCommand ${encoded}`, { encoding: "utf-8", windowsHide: true }).trim();
|
|
18
|
+
}
|
|
19
|
+
/** DPAPI-protect a Buffer, returns base64-encoded ciphertext. */
|
|
20
|
+
function dpapiProtect(data) {
|
|
21
|
+
const b64Input = data.toString("base64");
|
|
22
|
+
return runPS(`
|
|
23
|
+
Add-Type -AssemblyName System.Security
|
|
24
|
+
$bytes = [Convert]::FromBase64String("${b64Input}")
|
|
25
|
+
$enc = [System.Security.Cryptography.ProtectedData]::Protect(
|
|
26
|
+
$bytes, [byte[]]@(),
|
|
27
|
+
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
|
|
28
|
+
)
|
|
29
|
+
[Convert]::ToBase64String($enc)
|
|
30
|
+
`);
|
|
31
|
+
}
|
|
32
|
+
/** DPAPI-unprotect a base64-encoded ciphertext, returns Buffer. */
|
|
33
|
+
function dpapiUnprotect(b64Ciphertext) {
|
|
34
|
+
const result = runPS(`
|
|
35
|
+
Add-Type -AssemblyName System.Security
|
|
36
|
+
$enc = [Convert]::FromBase64String("${b64Ciphertext}")
|
|
37
|
+
$dec = [System.Security.Cryptography.ProtectedData]::Unprotect(
|
|
38
|
+
$enc, [byte[]]@(),
|
|
39
|
+
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
|
|
40
|
+
)
|
|
41
|
+
[Convert]::ToBase64String($dec)
|
|
42
|
+
`);
|
|
43
|
+
return Buffer.from(result, "base64");
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Read a session key file. Tries DPAPI-protected format first (.dpapi),
|
|
47
|
+
* falls back to plaintext hex. If plaintext found, migrates to DPAPI.
|
|
48
|
+
* Returns the raw key as a Buffer, or null if not found.
|
|
49
|
+
*/
|
|
50
|
+
export async function readSessionKey(keyPath) {
|
|
51
|
+
// Resolve symlinks so .dpapi file lands next to the real key
|
|
52
|
+
let resolvedPath = keyPath;
|
|
53
|
+
try {
|
|
54
|
+
resolvedPath = await realpath(keyPath);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
// realpath fails if file doesn't exist — use original
|
|
58
|
+
}
|
|
59
|
+
const dpapiPath = resolvedPath + ".dpapi";
|
|
60
|
+
// Try DPAPI-protected version first
|
|
61
|
+
if (IS_WINDOWS && existsSync(dpapiPath)) {
|
|
62
|
+
try {
|
|
63
|
+
const b64 = (await readFile(dpapiPath, "utf-8")).trim();
|
|
64
|
+
if (b64.length > 0)
|
|
65
|
+
return dpapiUnprotect(b64);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
// DPAPI decrypt failed — fall through to plaintext
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Try plaintext hex file
|
|
72
|
+
if (!existsSync(resolvedPath))
|
|
73
|
+
return null;
|
|
74
|
+
const hex = (await readFile(resolvedPath, "utf-8")).trim();
|
|
75
|
+
if (!/^[0-9a-f]{64}$/i.test(hex))
|
|
76
|
+
return null;
|
|
77
|
+
const key = Buffer.from(hex, "hex");
|
|
78
|
+
// Migrate: protect with DPAPI and save
|
|
79
|
+
if (IS_WINDOWS) {
|
|
80
|
+
try {
|
|
81
|
+
const protected64 = dpapiProtect(key);
|
|
82
|
+
await writeFile(dpapiPath, protected64, "utf-8");
|
|
83
|
+
// Don't delete the plaintext yet — Dash may still need it
|
|
84
|
+
// until Dash also uses this reader
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// DPAPI not available — keep using plaintext
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return key;
|
|
91
|
+
}
|
|
92
|
+
/** Check if DPAPI is available on this system. */
|
|
93
|
+
export function isDpapiAvailable() {
|
|
94
|
+
if (!IS_WINDOWS)
|
|
95
|
+
return false;
|
|
96
|
+
try {
|
|
97
|
+
dpapiProtect(Buffer.from("test"));
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=dpapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dpapi.js","sourceRoot":"","sources":["../../src/lib/dpapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal glob matcher for brain-relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - `**` — match any number of path segments (including zero)
|
|
6
|
+
* - `*` — match a single path segment (no slashes)
|
|
7
|
+
* - exact — literal string match
|
|
8
|
+
*
|
|
9
|
+
* No external dependencies. Used by vault policy + access manifests.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Test whether a brain-relative path matches a glob pattern.
|
|
13
|
+
*
|
|
14
|
+
* @param pattern - Glob pattern (e.g. "memory/**", "identity/*.md", "ops/audit.jsonl")
|
|
15
|
+
* @param path - Brain-relative path with forward slashes (e.g. "memory/semantic.jsonl")
|
|
16
|
+
*/
|
|
17
|
+
export declare function matchGlob(pattern: string, path: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Test whether a path matches ANY of the given glob patterns.
|
|
20
|
+
*/
|
|
21
|
+
export declare function matchAnyGlob(patterns: string[], path: string): boolean;
|
|
22
|
+
//# sourceMappingURL=glob-match.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-match.d.ts","sourceRoot":"","sources":["../../src/lib/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqCH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIhE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal glob matcher for brain-relative paths.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - `**` — match any number of path segments (including zero)
|
|
6
|
+
* - `*` — match a single path segment (no slashes)
|
|
7
|
+
* - exact — literal string match
|
|
8
|
+
*
|
|
9
|
+
* No external dependencies. Used by vault policy + access manifests.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Convert a glob pattern to a RegExp.
|
|
13
|
+
* Patterns are matched against forward-slash-normalized brain-relative paths.
|
|
14
|
+
*/
|
|
15
|
+
function globToRegex(pattern) {
|
|
16
|
+
// Normalize
|
|
17
|
+
const p = pattern.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
18
|
+
let regex = "^";
|
|
19
|
+
let i = 0;
|
|
20
|
+
while (i < p.length) {
|
|
21
|
+
if (p[i] === "*" && p[i + 1] === "*") {
|
|
22
|
+
// ** — match any depth (including zero segments)
|
|
23
|
+
// Consume trailing slash if present
|
|
24
|
+
i += 2;
|
|
25
|
+
if (p[i] === "/")
|
|
26
|
+
i++;
|
|
27
|
+
regex += "(?:.+/)?";
|
|
28
|
+
}
|
|
29
|
+
else if (p[i] === "*") {
|
|
30
|
+
// * — match single segment (no slashes)
|
|
31
|
+
regex += "[^/]+";
|
|
32
|
+
i++;
|
|
33
|
+
}
|
|
34
|
+
else if (".+?^${}()|[]\\".includes(p[i])) {
|
|
35
|
+
// Escape regex special chars
|
|
36
|
+
regex += "\\" + p[i];
|
|
37
|
+
i++;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
regex += p[i];
|
|
41
|
+
i++;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
regex += "$";
|
|
45
|
+
return new RegExp(regex);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Test whether a brain-relative path matches a glob pattern.
|
|
49
|
+
*
|
|
50
|
+
* @param pattern - Glob pattern (e.g. "memory/**", "identity/*.md", "ops/audit.jsonl")
|
|
51
|
+
* @param path - Brain-relative path with forward slashes (e.g. "memory/semantic.jsonl")
|
|
52
|
+
*/
|
|
53
|
+
export function matchGlob(pattern, path) {
|
|
54
|
+
const normalized = path.replace(/\\/g, "/");
|
|
55
|
+
const re = globToRegex(pattern);
|
|
56
|
+
return re.test(normalized);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Test whether a path matches ANY of the given glob patterns.
|
|
60
|
+
*/
|
|
61
|
+
export function matchAnyGlob(patterns, path) {
|
|
62
|
+
return patterns.some((p) => matchGlob(p, path));
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=glob-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"glob-match.js","sourceRoot":"","sources":["../../src/lib/glob-match.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,SAAS,WAAW,CAAC,OAAe;IAClC,YAAY;IACZ,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1D,IAAI,KAAK,GAAG,GAAG,CAAC;IAChB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACrC,iDAAiD;YACjD,oCAAoC;YACpC,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,CAAC,EAAE,CAAC;YACtB,KAAK,IAAI,UAAU,CAAC;QACtB,CAAC;aAAM,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACxB,wCAAwC;YACxC,KAAK,IAAI,OAAO,CAAC;YACjB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,6BAA6B;YAC7B,KAAK,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACrB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,CAAC;YACN,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACd,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IACD,KAAK,IAAI,GAAG,CAAC;IAEb,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe,EAAE,IAAY;IACrD,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,QAAkB,EAAE,IAAY;IAC3D,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized .locked file enforcement for brain paths.
|
|
3
|
+
*
|
|
4
|
+
* Shared by both MCP server (stdio) and direct file access (brain-io).
|
|
5
|
+
* Ensures locked paths are consistently protected regardless of access channel.
|
|
6
|
+
*
|
|
7
|
+
* Lock rules:
|
|
8
|
+
* - Exact path match (e.g. "identity/human.json")
|
|
9
|
+
* - Filename-only match (e.g. ".session-key" matches "identity/.session-key")
|
|
10
|
+
* - Directory prefix match (e.g. "identity/" matches "identity/foo.md")
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Read brain/.locked and merge with hardcoded minimums. Caches result.
|
|
14
|
+
* Safe to call multiple times — returns cached paths after first load.
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadLockedPaths(): Promise<string[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Synchronous variant — reads .locked file on first call, caches after.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadLockedPathsSync(): string[];
|
|
21
|
+
/** Force reload of locked paths (e.g. when listing current locks). */
|
|
22
|
+
export declare function reloadLockedPaths(): Promise<string[]>;
|
|
23
|
+
/** Get the currently cached locked paths. Loads synchronously if not yet cached. */
|
|
24
|
+
export declare function getLockedPaths(): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Check if a brain-relative path (forward slashes) is locked.
|
|
27
|
+
* Matches exact paths, filename-only, and directory prefixes.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isLocked(relPath: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Convert an absolute file path to a brain-relative path.
|
|
32
|
+
* Returns null if the path is not under brain/.
|
|
33
|
+
*/
|
|
34
|
+
export declare function toBrainRelativePath(absolutePath: string): string | null;
|
|
35
|
+
/**
|
|
36
|
+
* Assert that an absolute path is not locked. Throws if locked.
|
|
37
|
+
* No-op for paths outside brain/.
|
|
38
|
+
*/
|
|
39
|
+
export declare function assertNotLocked(absolutePath: string): void;
|
|
40
|
+
//# sourceMappingURL=locked.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locked.d.ts","sourceRoot":"","sources":["../../src/lib/locked.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAgBH;;;GAGG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAezD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAkB9C;AAED,sEAAsE;AACtE,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAG3D;AAED,oFAAoF;AACpF,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAGzC;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAajD;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASvE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAM1D"}
|