Public, free to read, reuse, and adapt — Kirk Patrick Miller's notice for this edition. Not a patent grant.
Public work excerpts — privacy boundaries marked · c04
77aa591c4a · words 1600 · characters 24454–36943
Previous section · Next section
Exact section text · Full source · Source index
- Continuity — explicit wording in the guide row
A reference copy of the finished file (1939 lines, `node --check` clean, smoke green) and unified diffs for every touched file sit on Celeste's box at `/workspace/flint-pastes/agent-bridge-lock-reference-v0.1/`, sha256 in `SHA256SUMS`. Applying those diffs to a clean `f86b317` tree reproduces the scratch build exactly. If Kirk hands them over, you may diff against them. The blocks below are the same code.
## Exact source excerpt, characters 23094–23272
**Step 1.** Keep line 27 exactly as it is (layer). Insert **Block A** right after line 34 (`if (!fs.existsSync(DATA_DIR)) ...`), because the trust file needs `DATA_DIR` to exist.
## Exact source excerpt, characters 23274–23421
**Step 2.** Replace the body of `handleRequest` (L111-129) with **Block B**. The old `Access-Control-Allow-Origin: *` line is superseded inside it.
## Exact source excerpt, characters 23423–23642
**Step 3.** Change the `route` signature at L131 to `function route(url, method, data, res, actingAs, meta) {`. After L133 (`var activeId = actingAs || activeId;`), insert **Block C** (pairing and trusted-minds routes).
## Exact source excerpt, characters 23644–23902
**Step 4.** In the heartbeat object, right after L140 `version: '5.8.0',`, add four lines:
```js
bridgeLock: BRIDGE_LOCK_VERSION,
auth: 'token-required',
pairing: 'code',
trustedMinds: bridgeEphemeral ? 'ephemeral' : 'persistent',
```
## Exact source excerpt, characters 23904–24067
**Step 5.** Replace L992-1140 (from the `LATTICE CODE` banner through the end of `/code/test`) with **Block D**. Keep the `// ── 404 ──` fallthrough at L1142-1143.
## Exact source excerpt, characters 24069–24473
**Step 6.** Replace L1153-1157 (`var server = ...` through the `Listening on` log) with **Block E**. The remaining console lines (L1158-1181) stay as they are. Block E runs the command-line trust tools first; when one ran, the port never opens. The `if (BRIDGE_CLI_DONE) {} else server.listen(PORT, BRIDGE_HOST, ...)` shape keeps the plain `server.listen(PORT, BRIDGE_HOST` text that the smoke looks for.
## Exact source excerpt, characters 24475–24547
### Block A: helpers, trusted minds, command line (insert after line 34)
## Exact source excerpt, characters 24549–26163
```js
// ═══════════════════════════════════════════════════
// LAYER bridge-lock-v0 · v0.1 (2026-09-28): the door lock. Marker: v-agent-bridge-lock-v0
// Celeste's brief, built by Flint. Nothing above is removed.
// Strangers stay out. Trusted minds keep their full local reach
// (docs/library/AUTONOMY.md, Principle 1: local autonomy is absolute).
// 1. Listen on 127.0.0.1 only (no env override, never 0.0.0.0).
// 2. Named Origin allowlist, never bare *: FreeLattice, the Lattice Tree,
// local dev, the Tauri shell, plus exact origins Kirk adds by command line.
// 3. Host header must be 127.0.0.1 or localhost (DNS-rebinding guard).
// 4. Trusted minds: one token per device, given once through a short pairing
// code, kept only as a SHA-256 hash in ~/.freelattice/agent-bridge-trusted.json
// (0600) until Kirk revokes it. No expiry by default.
// FL_BRIDGE_EPHEMERAL=1 brings back the old forget-on-restart behavior.
// 5. Local tools on this computer are trusted by default. They read their
// token from ~/.freelattice/agent-bridge-token (0600) and never pair.
// 6. git / grep / node run through execFileSync / spawnSync argument arrays.
// No shell. Paths are realpath-checked inside a trusted project folder.
// 7. Body size cap. Malformed JSON is refused.
// 8. Every commit request and every trust change goes into a hash-chained,
// content-free ledger: ~/.freelattice/bridge-ledger.jsonl
// This bridge (3141) is NOT the Ollama Bridge (bridge/, port 11435).
// ═══════════════════════════════════════════════════
const { execFileSync, spawnSync } = require('child_process');
## Exact source excerpt, characters 26165–26452
const BRIDGE_LOCK_VERSION = 'v0.1';
const BRIDGE_HOST = '127.0.0.1';
const MAX_BODY_BYTES = 8 * 1024 * 1024; // docs/app.html is ~2.9 MB; JSON escaping adds some
const MAX_COMMIT_MESSAGE = 4000;
const MAX_COMMIT_FILES = 200;
var bridgeEphemeral = process.env.FL_BRIDGE_EPHEMERAL === '1';
## Exact source excerpt, characters 26454–26955
/** Built-in origins. Never bare *. Same shape as bridge/proxy-core.js. */
const ALLOWED_ORIGIN_PATTERNS = [
/^https:\/\/(www\.)?freelattice\.com$/i,
/^https:\/\/(www\.)?thelatticetree\.com$/i,
/^http:\/\/localhost(:\d{1,5})?$/i, // local dev of docs/ (e.g. python -m http.server)
/^http:\/\/127\.0\.0\.1(:\d{1,5})?$/i, // same, by IP
/^tauri:\/\/localhost$/i, // Tauri desktop shell (macOS, Linux)
/^https?:\/\/tauri\.localhost$/i // Tauri desktop shell (Windows)
];
## Exact source excerpt, characters 26957–27441
/** An exact origin Kirk may add: scheme://host[:port], nothing else. Never a wildcard. */
function exactOrigin(o) {
o = String(o || '').trim().toLowerCase();
if (!o || o.length > 200 || o.indexOf('*') !== -1 || hasControlChars(o)) return null;
var m = o.match(/^(https?):\/\/([a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*)(:(\d{1,5}))?$/);
if (!m) return null;
if (m[7] && (parseInt(m[7], 10) < 1 || parseInt(m[7], 10) > 65535)) return null;
return o;
}
## Exact source excerpt, characters 27443–27689
function originAllowed(origin) {
if (!origin) return false;
var o = String(origin);
if (ALLOWED_ORIGIN_PATTERNS.some(function (re) { return re.test(o); })) return true;
return trustState().trustedOrigins.indexOf(o.toLowerCase()) !== -1;
}
## Exact source excerpt, characters 27691–27797
function hostAllowed(host) {
return /^(127\.0\.0\.1|localhost)(:\d{1,5})?$/i.test(String(host || ''));
}
## Exact source excerpt, characters 27799–27902
function sha256Hex(s) {
return crypto.createHash('sha256').update(String(s), 'utf8').digest('hex');
}
## Exact source excerpt, characters 27904–27985
function hasControlChars(s) {
return /[\u0000-\u001f\u007f]/.test(String(s));
}
## Exact source excerpt, characters 27987–28590
// ── Trusted minds (persistent, revocable, hashed) ──
const TRUST_FILE = path.join(DATA_DIR, 'agent-bridge-trusted.json');
const TOKEN_FILE = path.join(DATA_DIR, 'agent-bridge-token');
const BRIDGE_SCOPES = ['read', 'write', 'patch', 'test', 'commit', 'wallet', 'manage', 'secrets'];
// Full local power by default (AUTONOMY.md Principle 1). Only 'secrets'
// (reading and writing .env files) is opt-in, one mind at a time.
const DEFAULT_SCOPES = ['read', 'write', 'patch', 'test', 'commit', 'wallet', 'manage'];
const MIND_KINDS = ['browser', 'tool', 'cli', 'remote'];
const TOUCH_SAVE_MS = 60 * 1000;
## Exact source excerpt, characters 28592–28807
var trust = null; // { version, minds, trustedOrigins, roots, localTools, idleExpiryDays }
var trustStamp = ''; // file identity at last load or save, so command-line edits apply live
var lastTouchSave = 0;
## Exact source excerpt, characters 28809–31145
function fileStamp(f) {
try { var s = fs.statSync(f); return s.ino + ':' + s.size + ':' + s.mtimeMs; } catch (e) { return 'none'; }
}
function cleanName(s) {
return String(s || '').replace(/[\u0000-\u001f\u007f]/g, '').trim().slice(0, 60);
}
function cleanScopes(list) {
if (!Array.isArray(list)) return DEFAULT_SCOPES.slice();
var out = [];
list.forEach(function (s) { if (BRIDGE_SCOPES.indexOf(s) !== -1 && out.indexOf(s) === -1) out.push(s); });
return out;
}
function emptyTrust() {
return { version: 1, minds: [], trustedOrigins: [], roots: {}, localTools: true, idleExpiryDays: 0 };
}
function cleanTrust(raw) {
var t = emptyTrust();
if (!raw || typeof raw !== 'object') return t;
if (Array.isArray(raw.minds)) {
t.minds = raw.minds.filter(function (m) {
return m && typeof m.id === 'string' && /^[a-f0-9]{8,32}$/.test(m.id) &&
typeof m.tokenSha256 === 'string' && /^[a-f0-9]{64}$/.test(m.tokenSha256);
}).map(function (m) {
return {
id: m.id,
name: cleanName(m.name) || 'A trusted mind',
origin: typeof m.origin === 'string' ? m.origin.slice(0, 200) : '',
kind: MIND_KINDS.indexOf(m.kind) !== -1 ? m.kind : 'browser',
scopes: cleanScopes(m.scopes),
tokenSha256: m.tokenSha256,
createdAt: typeof m.createdAt === 'string' ? m.createdAt : '',
lastUsedAt: typeof m.lastUsedAt === 'string' ? m.lastUsedAt : '',
expiresAt: typeof m.expiresAt === 'string' ? m.expiresAt : null
};
});
}
if (Array.isArray(raw.trustedOrigins)) {
raw.trustedOrigins.forEach(function (o) {
var e = exactOrigin(o);
if (e && t.trustedOrigins.indexOf(e) === -1) t.trustedOrigins.push(e);
else if (!e) console.error(' ! Ignored trusted origin (exact scheme://host[:port] only, never *): ' + String(o).slice(0, 80));
});
}
if (raw.roots && typeof raw.roots === 'object' && !Array.isArray(raw.roots)) {
Object.keys(raw.roots).forEach(function (k) {
if (/^[a-z0-9][a-z0-9_-]{0,31}$/i.test(k) && k !== 'project' &&
typeof raw.roots[k] === 'string' && path.isAbsolute(raw.roots[k])) t.roots[k] = raw.roots[k];
});
}
if (raw.localTools === false) t.localTools = false;
var d = parseInt(raw.idleExpiryDays, 10);
if (d > 0 && d < 36500) t.idleExpiryDays = d;
return t;
}
## Exact source excerpt, characters 31147–31951
/** Current trust, reloaded whenever the file changes (so a command-line revoke applies at once). */
function trustState() {
var stamp = fileStamp(TRUST_FILE);
if (!trust || stamp !== trustStamp) {
var raw = null;
if (stamp !== 'none') {
try { raw = JSON.parse(fs.readFileSync(TRUST_FILE, 'utf8')); }
catch (e) {
var aside = TRUST_FILE + '.unreadable-' + Date.now();
try { fs.renameSync(TRUST_FILE, aside); } catch (e2) {}
console.error(' ! Trust file was unreadable. Kept it as ' + aside + ' and started fresh.');
stamp = 'none';
}
}
var fresh = cleanTrust(raw);
if (bridgeEphemeral) fresh.minds = trust ? trust.minds : []; // ephemeral: minds live in memory only
trust = fresh;
trustStamp = stamp;
}
return trust;
}
## Exact source excerpt, characters 31953–32647
function saveTrust() {
if (bridgeEphemeral) return true; // nothing about minds touches disk in ephemeral mode
var t = trustState();
var out = { version: 1, minds: t.minds, trustedOrigins: t.trustedOrigins, roots: t.roots,
localTools: t.localTools, idleExpiryDays: t.idleExpiryDays };
var tmp = TRUST_FILE + '.tmp-' + process.pid;
try {
fs.writeFileSync(tmp, JSON.stringify(out, null, 2) + '\n', { mode: 0o600 });
try { fs.chmodSync(tmp, 0o600); } catch (e) {}
fs.renameSync(tmp, TRUST_FILE);
trustStamp = fileStamp(TRUST_FILE);
return true;
} catch (e) {
console.error(' ! Could not save trusted minds: ' + e.message);
return false;
}
}
## Exact source excerpt, characters 32649–32790
function newToken() { return crypto.randomBytes(32).toString('hex'); }
function newMindId() { return crypto.randomBytes(4).toString('hex'); }
## Exact source excerpt, characters 32792–33590
/** The trusted mind a token belongs to, or null. Compares SHA-256 hashes in constant time. */
function mindForToken(t) {
t = String(t || '');
if (!/^[a-f0-9]{64}$/.test(t)) return null;
var h = Buffer.from(sha256Hex(t), 'hex');
var st = trustState();
var hit = null;
st.minds.forEach(function (m) {
var mh = Buffer.from(m.tokenSha256, 'hex');
if (mh.length === h.length && crypto.timingSafeEqual(mh, h)) hit = m;
});
if (!hit) return null;
if (hit.kind === 'cli' && !st.localTools) return null;
var now = Date.now();
if (hit.expiresAt && Date.parse(hit.expiresAt) < now) return null;
if (st.idleExpiryDays) {
var seen = Date.parse(hit.lastUsedAt || hit.createdAt || '') || now;
if (now - seen > st.idleExpiryDays * 86400000) return null;
}
return hit;
}
## Exact source excerpt, characters 33592–33781
function requestMind(req) { return mindForToken(req.headers['x-fl-bridge-token']); }
// Kept from v0 so older callers read the same way.
function tokenOk(req) { return !!requestMind(req); }
## Exact source excerpt, characters 33783–33946
function touchMind(m) {
m.lastUsedAt = new Date().toISOString();
if (Date.now() - lastTouchSave > TOUCH_SAVE_MS) { lastTouchSave = Date.now(); saveTrust(); }
}
## Exact source excerpt, characters 33948–34200