Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
060f91d
feat: add durable private-turn observers and workflow artifacts
ShahryarAbbasi Aug 28, 2026
61ced16
fix: make private-turn observation crash-safe
ShahryarAbbasi Aug 28, 2026
fa99cf7
fix: isolate and cancel private-turn observer delivery
ShahryarAbbasi Aug 28, 2026
a24535b
feat: add signed schedule fire authority
ShahryarAbbasi Aug 28, 2026
719f315
Merge durable artifacts and signed schedule authority
ShahryarAbbasi Aug 28, 2026
78c9fad
fix: isolate signed scheduled runs from run controls
ShahryarAbbasi Aug 28, 2026
5e38a94
fix: preserve ordinary signal polling timing
ShahryarAbbasi Aug 28, 2026
cdf8d7a
Merge remote-tracking branch 'upstream/main' into codex/durable-artif…
ShahryarAbbasi Aug 28, 2026
dbd2880
test: follow delivered file renderer extraction
ShahryarAbbasi Aug 28, 2026
49b3ac0
fix: close schedule authority and delivery gaps
ShahryarAbbasi Aug 28, 2026
adfb5a4
fix: fence signed run finalization
ShahryarAbbasi Aug 28, 2026
9c455e1
feat: add transient Gemini dev provider
ShahryarAbbasi Aug 28, 2026
51f2db0
feat(slack): add native agent streams and workflow cards
ShahryarAbbasi Aug 28, 2026
fb813aa
fix(slack): settle native agent sessions safely
ShahryarAbbasi Aug 29, 2026
e8861b0
fix: start requested Google reads without redundant permission prompts
ShahryarAbbasi Aug 28, 2026
feba29d
Add fixed-tool approval and runtime attestation contracts
ShahryarAbbasi Aug 29, 2026
89f2a6b
Fix immutable GitHub CLI install for MicroVMs
16francej Aug 28, 2026
ef366a1
Build web assets on the native executor
ShahryarAbbasi Aug 29, 2026
43d5262
Repair PostgreSQL search parallel safety
ShahryarAbbasi Aug 29, 2026
acae0d2
Harden HTTP MCP connector contracts
ShahryarAbbasi Aug 29, 2026
a090711
feat(mcp): bind founder analytics authority
ShahryarAbbasi Aug 31, 2026
ce5fe90
fix(mcp): seal native analytics deliveries
ShahryarAbbasi Aug 31, 2026
7bd9495
fix(mcp): harden founder analytics authority delivery
ShahryarAbbasi Aug 31, 2026
712369e
fix(mcp): require canonical analytics email authority
ShahryarAbbasi Aug 31, 2026
8355d71
fix(mcp): bind rotated cards to fixed authority
ShahryarAbbasi Aug 31, 2026
0572d60
Merge current main into reviewed MCP analytics stack
ShahryarAbbasi Aug 31, 2026
43ccb62
fix(model): keep forced Gemini ahead of individual auth
ShahryarAbbasi Aug 31, 2026
1ed5620
fix(ci): restore analytics integration gates
ShahryarAbbasi Aug 31, 2026
2df95bd
test(ci): harden strict runtime gates
ShahryarAbbasi Aug 31, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .codex/skills/dev-instance/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ The dev instance should exercise the real system:
check. The auth-file path is for local dev instances; deployed production processes
use an API key or a keychain credential (`CODEX_AUTH_CREDENTIAL` /
`CLAUDE_AUTH_CREDENTIAL`), whose secret lives encrypted in its owner's keychain.
- Gemini: an exported `GEMINI_API_KEY` selects `HARNESS=pi`, the transient
`google-gemini-dev` custom provider, Google's exact OpenAI-compatible endpoint, and
`gemini-3.7-flash`. Conflicting harness, endpoint, provider, or model settings are
refused. The launcher does not alias the key to another vendor, write it into the lease
boot spec, expose it to non-core children or supervisor helpers, or store it in the
custom-provider database. Stored and per-request runtime choices cannot override it.
- real durability: uses `DATABASE_URL` when supplied; otherwise starts/reuses a local
Docker Postgres container and runs core with `SESSION_STORE=postgres` and
`RUN_STORE=postgres`
Expand Down Expand Up @@ -161,6 +167,12 @@ The launcher reads values from, in priority order: exported shell env, the machi
worktree's `.env` (seeded from the main checkout in linked worktrees). Slack pool tokens
default to `~/.config/qm/slack-pool`.

`GEMINI_API_KEY` is deliberately process-only. Load it into the environment of the `up`
command without printing it. Run `down`, then unset it after QA. The launcher refuses to read this key
from `dev.env` or `.env`; `GEMINI_BASE_URL`, when present, must be
`https://generativelanguage.googleapis.com/v1beta/openai`, and `GEMINI_MODEL`, when
present, must be `gemini-3.7-flash`.

When a cloud sandbox backend is configured it also validates that provider's access at
startup, refreshes a stale provider token from the provider CLI's own logged-in session
where it can, and — if a tunnel binary is present — opens a quick tunnel so sandbox
Expand Down
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,21 @@ CAPABILITY_SECRET=
PORTAL_IDENTITY_SECRET=
CONNECTOR_SECRET_KEY=
SKILL_SIGNING_SECRET=
PRIVATE_TURN_OBSERVER_URL=
PRIVATE_TURN_OBSERVER_SIGNING_SECRET=
SCHEDULE_AUTHORITY_REF=
SCHEDULE_AUTHORITY_ISSUER_REF=
SCHEDULE_AUTHORITY_KEY_ID=
SCHEDULE_AUTHORITY_SIGNING_JWK=
QM_MCP_AUTHORITY_ISSUER=
QM_MCP_AUTHORITY_ORGANIZATION_ID=
QM_MCP_AUTHORITY_PRINCIPAL_ID=
QM_MCP_AUTHORITY_SLACK_TEAM_ID=
QM_MCP_AUTHORITY_SLACK_USER_ID=
QM_MCP_AUTHORITY_SLACK_DM_CHANNEL_ID=
QM_MCP_AUTHORITY_ED25519_PRIVATE_KEY=
QM_MCP_AUTHORITY_ED25519_PREVIOUS_PUBLIC_KEYS=
QM_MCP_AUTHORITY_TTL_SECONDS=30

RATE_LIMIT_PER_WINDOW=60
RATE_LIMIT_WINDOW_MS=60000
Expand Down
53 changes: 52 additions & 1 deletion aws/microvm-agent/agent.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import path from "node:path";

const PORT = Number(process.env.AGENT_PORT || 8080);
const MAX_BUFFER = 256 * 1024 * 1024;
const MAX_ATTEST_EXECUTABLE = 1024 * 1024;
const START_MS = Date.now();

function readBody(req, cap = MAX_BUFFER) {
Expand Down Expand Up @@ -71,6 +72,53 @@ async function handleRead(req, res) {
send(res, 200, { b64: buf.toString("base64") });
}

export function readAttestedExecutable(binary, root = "/usr/local/bin") {
if (typeof binary !== "string" || !/^[a-z0-9][a-z0-9-]{0,63}$/.test(binary)) {
throw new Error("invalid binary");
}
const canonicalRoot = fs.realpathSync(root);
const target = path.join(root, binary);
const canonicalTarget = path.join(canonicalRoot, binary);
const before = fs.lstatSync(target);
if (
!before.isFile() ||
before.isSymbolicLink() ||
before.size > MAX_ATTEST_EXECUTABLE ||
(before.mode & 0o111) === 0
) {
throw new Error("invalid executable");
}
if (fs.realpathSync(target) !== canonicalTarget) throw new Error("invalid executable path");
const fd = fs.openSync(target, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
try {
const opened = fs.fstatSync(fd);
if (!opened.isFile() || opened.size > MAX_ATTEST_EXECUTABLE || (opened.mode & 0o111) === 0) {
throw new Error("invalid executable");
}
const bytes = Buffer.allocUnsafe(MAX_ATTEST_EXECUTABLE + 1);
let length = 0;
for (;;) {
const read = fs.readSync(fd, bytes, length, bytes.length - length, null);
if (read === 0) break;
length += read;
if (length > MAX_ATTEST_EXECUTABLE) throw new Error("executable too large");
}
return { bytes: bytes.subarray(0, length), mode: opened.mode & 0o777 };
} finally {
fs.closeSync(fd);
}
}

async function handleAttestExecutable(req, res) {
const body = JSON.parse((await readBody(req, 1024)).toString("utf8") || "{}");
try {
const { bytes, mode } = readAttestedExecutable(body.binary);
return send(res, 200, { b64: bytes.toString("base64"), size: bytes.length, mode });
} catch (error) {
return send(res, 409, { error: error instanceof Error ? error.message : "attestation failed" });
}
}

const server = http.createServer((req, res) => {
const route = (req.url || "").split("?")[0];
(async () => {
Expand All @@ -84,8 +132,11 @@ const server = http.createServer((req, res) => {
if (req.method === "POST" && route === "/exec") return handleExec(req, res);
if (req.method === "POST" && route === "/write") return handleWrite(req, res);
if (req.method === "POST" && route === "/read") return handleRead(req, res);
if (req.method === "POST" && route === "/attest-executable") return handleAttestExecutable(req, res);
return send(res, 404, { error: "not found", route });
})().catch((e) => send(res, 500, { error: String((e && e.message) || e) }));
});

server.listen(PORT, "0.0.0.0", () => console.log(`[microvm-agent] exec daemon listening on ${PORT}`));
if (import.meta.main) {
server.listen(PORT, "0.0.0.0", () => console.log(`[microvm-agent] exec daemon listening on ${PORT}`));
}
132 changes: 125 additions & 7 deletions cli/src/sandbox-layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { join } from "node:path";
import { JUNK_FILE, deploymentLayerBundle } from "./deployment-layer.ts";
import { errMessage } from "./log.ts";

export type ApprovalDecision = "require_approval" | "deny";
export type ApprovalDecision = "allow" | "require_approval" | "deny";

const isPlainObject = (v: unknown): v is Record<string, unknown> =>
typeof v === "object" && v !== null && !Array.isArray(v);
Expand All @@ -27,6 +27,8 @@ export interface ToolApproval {
pattern?: string;
decision?: ApprovalDecision;
reason?: string;
approvalScope?: "rule" | "command";
subsumesToolApproval?: true;
}

export interface ToolAuthDescriptor {
Expand Down Expand Up @@ -59,6 +61,8 @@ export interface ToolDescriptor {
auth?: ToolAuthDescriptor;
approvals?: ToolApproval[];
install?: { binary?: string };
selfCheck?: { kind: "executable-sha256-v1" };
requestWorkspace?: { maxBytes: number };
}

export function parseToolDescriptor(raw: string, sourcePath: string): ToolDescriptor {
Expand Down Expand Up @@ -122,6 +126,37 @@ export function parseToolDescriptor(raw: string, sourcePath: string): ToolDescri
out.install = binary !== undefined ? { binary } : {};
}

if (d["selfCheck"] !== undefined) {
const selfCheck = d["selfCheck"];
if (!isPlainObject(selfCheck)) {
throw new Error(`${sourcePath}: "selfCheck" must be an object`);
}
const keys = Object.keys(selfCheck);
if (keys.length !== 1 || !keys.includes("kind")) {
throw new Error(`${sourcePath}: "selfCheck" supports only kind`);
}
if (selfCheck["kind"] !== "executable-sha256-v1") {
throw new Error(`${sourcePath}: "selfCheck.kind" must be executable-sha256-v1`);
}
out.selfCheck = { kind: "executable-sha256-v1" };
}

if (d["requestWorkspace"] !== undefined) {
const requestWorkspace = d["requestWorkspace"];
if (!isPlainObject(requestWorkspace)) throw new Error(`${sourcePath}: "requestWorkspace" must be an object`);
if (Object.keys(requestWorkspace).some((key) => key !== "maxBytes")) {
throw new Error(`${sourcePath}: "requestWorkspace" only accepts "maxBytes"`);
}
if (
!Number.isInteger(requestWorkspace["maxBytes"]) ||
(requestWorkspace["maxBytes"] as number) < 1 ||
(requestWorkspace["maxBytes"] as number) > 20 * 1024 * 1024
) {
throw new Error(`${sourcePath}: "requestWorkspace.maxBytes" must be an integer from 1 through 20971520`);
}
out.requestWorkspace = { maxBytes: requestWorkspace["maxBytes"] as number };
}

const credentialPaths = out.auth?.credentialPaths ?? [];
for (const [index, credentialPath] of credentialPaths.entries()) {
const { path, kind } = credentialPath;
Expand Down Expand Up @@ -189,6 +224,11 @@ export function parseToolDescriptor(raw: string, sourcePath: string): ToolDescri
`${sourcePath}: approvals[${i}].pattern must refer to its own tool binary by starting with \\b${binary}\\b and may not use a top-level alternative`,
);
}
if (approval.subsumesToolApproval && !safeSubsumingPattern(binary, compiled.pattern)) {
throw new Error(
`${sourcePath}: approvals[${i}].subsumesToolApproval requires an anchored single-command safe pattern`,
);
}
}

return out;
Expand Down Expand Up @@ -304,15 +344,42 @@ function parseApprovals(raw: unknown, sourcePath: string): ToolApproval[] {
if (hasPattern) out.pattern = e["pattern"] as string;
if (e["decision"] !== undefined) {
const dec = e["decision"];
if (dec !== "require_approval" && dec !== "deny") {
throw new Error(`${sourcePath}: approvals[${i}].decision must be require_approval or deny`);
if (dec !== "allow" && dec !== "require_approval" && dec !== "deny") {
throw new Error(`${sourcePath}: approvals[${i}].decision must be allow, require_approval, or deny`);
}
out.decision = dec;
}
if (e["reason"] !== undefined) {
if (typeof e["reason"] !== "string") throw new Error(`${sourcePath}: approvals[${i}].reason must be a string`);
out.reason = e["reason"];
}
if (e["approvalScope"] !== undefined) {
if (e["approvalScope"] !== "rule" && e["approvalScope"] !== "command") {
throw new Error(`${sourcePath}: approvals[${i}].approvalScope must be rule or command`);
}
if (e["approvalScope"] === "command" && (e["decision"] ?? "require_approval") !== "require_approval") {
throw new Error(`${sourcePath}: approvals[${i}].approvalScope command requires decision require_approval`);
}
out.approvalScope = e["approvalScope"];
}
if (e["subsumesToolApproval"] !== undefined) {
if (e["subsumesToolApproval"] !== true) {
throw new Error(`${sourcePath}: approvals[${i}].subsumesToolApproval must be true`);
}
if (!hasPattern) {
throw new Error(`${sourcePath}: approvals[${i}].subsumesToolApproval requires an exact pattern`);
}
if ((e["decision"] ?? "require_approval") === "deny") {
throw new Error(`${sourcePath}: approvals[${i}].subsumesToolApproval cannot be used with deny`);
}
if ((e["decision"] ?? "require_approval") === "require_approval" && e["approvalScope"] !== "command") {
throw new Error(`${sourcePath}: approvals[${i}].subsumesToolApproval requires command-scoped write approval`);
}
out.subsumesToolApproval = true;
}
if (out.decision === "allow" && out.subsumesToolApproval !== true) {
throw new Error(`${sourcePath}: approvals[${i}].decision allow requires subsumesToolApproval`);
}
return out;
});
}
Expand All @@ -322,6 +389,36 @@ const SPLIT_ENV_KEY_RE = /^[A-Z][A-Z0-9_]*$/;
const POSIX_FUNCTION_NAME_RE = /^[a-z_][a-z0-9_]*$/;

const MAX_APPROVAL_PATTERN_LEN = 256;
function safeSubsumingPattern(binary: string, pattern: string): boolean {
const prefix = `^${escapeRegex(binary)} `;
if (!pattern.startsWith(prefix) || !pattern.endsWith("$") || pattern.includes("\n") || pattern.includes("\r"))
return false;
for (let i = prefix.length; i < pattern.length - 1; i++) {
const char = pattern[i]!;
if (/[A-Za-z0-9 _@%=,:/_-]/.test(char)) continue;
if (char === "\\" && pattern[i + 1] === ".") {
i++;
continue;
}
if (char === "[") {
const end = pattern.indexOf("]", i + 1);
if (end < 0 || !["A-Za-z0-9", "A-Za-z0-9_-", "A-Za-z0-9._-", "a-f0-9"].includes(pattern.slice(i + 1, end))) {
return false;
}
i = end;
continue;
}
if (char === "{") {
const quantifier = pattern.slice(i).match(/^\{(\d+)(?:,(\d+))?\}/);
if (!quantifier || Number(quantifier[2] ?? quantifier[1]) > 256) return false;
i += quantifier[0].length - 1;
continue;
}
return false;
}
return true;
}

function approvalPatternTooSlow(pattern: string): boolean {
if (/\\[1-9]|\\k<[^>]+>/.test(pattern)) return true;
type AtomChars = { ascii: Set<number>; asciiOnly: boolean };
Expand Down Expand Up @@ -590,7 +687,8 @@ function approvalPatternTooSlow(pattern: string): boolean {
const escapeRegex = (s: string): string => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");

function rawApprovalTargetsTool(binary: string, pattern: string): boolean {
if (!pattern.startsWith(`\\b${escapeRegex(binary)}\\b`)) return false;
if (!pattern.startsWith(`\\b${escapeRegex(binary)}\\b`) && !pattern.startsWith(`^${escapeRegex(binary)} `))
return false;
let depth = 0;
let inClass = false;
let escaped = false;
Expand Down Expand Up @@ -619,12 +717,32 @@ function rawApprovalTargetsTool(binary: string, pattern: string): boolean {
return true;
}

export function compileApproval(binary: string, a: ToolApproval): { pattern: string; decision: ApprovalDecision } {
export function compileApproval(
binary: string,
a: ToolApproval,
): {
pattern: string;
decision: ApprovalDecision;
approvalScope?: "rule" | "command";
subsumesToolApproval?: true;
} {
const decision: ApprovalDecision = a.decision ?? "require_approval";
if (a.pattern !== undefined) return { pattern: a.pattern, decision };
if (a.pattern !== undefined) {
return {
pattern: a.pattern,
decision,
...(a.approvalScope ? { approvalScope: a.approvalScope } : {}),
...(a.subsumesToolApproval ? { subsumesToolApproval: true as const } : {}),
};
}
const words = (a.command ?? "").trim().split(/\s+/).filter(Boolean).map(escapeRegex);
const pattern = `\\b${[escapeRegex(binary), ...words].join("\\s+")}(?:\\b|\\s|$)`;
return { pattern, decision };
return {
pattern,
decision,
...(a.approvalScope ? { approvalScope: a.approvalScope } : {}),
...(a.subsumesToolApproval ? { subsumesToolApproval: true as const } : {}),
};
}

type SplitEnvContext = { actingSlackUserId?: string };
Expand Down
Loading