ReviewOS

also looking at this

stacks/drone

feat: add declared VTOL recovery and landing routes

#80
Merged chris wants to merge codex/owned-vtol-recovery-route into main
13 files +558 -52

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

.github/workflows/ci.ymlmodified+2-0
Changes to .github/workflows/ci.yml
@@ -491,6 +491,8 @@ jobs:
491491 ${{ runner.temp }}/execution-browser-evidence/*.png
492492 ${{ runner.temp }}/execution-browser-evidence/compiled.html
493493 ${{ runner.temp }}/execution-browser-evidence/browser-launch.json
494 ${{ runner.temp }}/execution-browser-evidence/failure-diagnostics.json
495 ${{ runner.temp }}/execution-browser-evidence/admission-renewal.json
494496 ${{ runner.temp }}/execution-browser-evidence/chrome-startup-stderr.log
495497 purge-namespace:
496498 runs-on: ubuntu-latest
tests/fixtures/public-safety-access/execution-browser.tsmodified+26-7
Changes to tests/fixtures/public-safety-access/execution-browser.ts
@@ -21,6 +21,8 @@ const { executionWords: words } = await import('../../../resources/functions/dro
2121let holdArmed = false, holdUsed = false, held = false, releaseCredit: (() => void) | undefined
2222let delayStart = true, releaseStart: (() => void) | undefined
2323let streamStarts = 0, startRequests = 0, admissionRequests = 0, closeStream: (() => Promise<void>) | undefined
24let closeWorkspaceStream: (() => Promise<void>) | undefined, releaseWorkspace: (() => void) | undefined
25let holdWorkspace = false, workspaceHeld = false
2426
2527// Diagnostic state belongs only to this disposable fixture, never the execution controller.
2628type RouteClass = 'execution-start' | 'execution-close' | 'execution-admission' | 'execution-events' | 'execution-status' | 'workspace-read'
@@ -51,7 +53,7 @@ function diagnosticSnapshot() {
5153 }
5254 return {
5355 available: true, pendingChecks: scalar(owner.pendingChecks),
54 fixture: { startRequests, admissionRequests, streamStarts, holdArmed, held, holdUsed }, lastStart, lastAdmission, responses: responses.slice(),
56 fixture: { startRequests, admissionRequests, streamStarts, holdArmed, held, holdUsed, holdWorkspace, workspaceHeld }, lastStart, lastAdmission, responses: responses.slice(),
5557 slot: slot === null ? null : {
5658 ordinal: ordinal(slot),
5759 phase: choice(field(slot, 'phase'), ['waiting-for-consumer', 'running', 'stopping', 'completed', 'canceled', 'failed', 'discarded'] satisfies ExecutionView['phase'][]),
@@ -138,8 +140,15 @@ const control = async (request: Request) => {
138140 assert(rows.some(row => row.digest !== seeded.source.digest))
139141 const committed = await fixture.snapshot(seeded.key)
140142 assert.equal(committed.audits.filter(audit => audit.action === 'source-registered').length, 2)
143 holdWorkspace = true
144 assert(closeWorkspaceStream, 'The real workspace stream must exist before renewal')
145 await closeWorkspaceStream()
146 const until = Date.now() + 5000
147 while (!workspaceHeld && Date.now() < until) await Bun.sleep(5)
148 assert(workspaceHeld, 'Native workspace renewal must request a fresh authorized snapshot')
141149 return Response.json({ ok: true })
142150 }
151 if (action === 'release-workspace') { assert(workspaceHeld, 'Release only the held native renewal'); releaseWorkspace?.(); return Response.json({ ok: true }) }
143152 if (action === 'read-only') return Response.json({ token: await fixture.credential(fixture.sender.id, ['public-safety:read']) })
144153 if (action === 'revoke') { await fixture.tokens.revokeToken(fixture.senderToken); return Response.json({ ok: true }) }
145154 return new Response(null, { status: 404 })
@@ -153,15 +162,25 @@ route.use(async (request: Request, next: () => Promise<Response | null> | Respon
153162 if (admissionOrdinal !== null) lastAdmission = { ordinal: admissionOrdinal, settled: false, status: null, elapsedMs: null }
154163 let status: number | null = null
155164 try {
165 if (kind === 'workspace-read' && holdWorkspace) {
166 holdWorkspace = false; workspaceHeld = true
167 await new Promise<void>(resolve => {
168 const release = () => { workspaceHeld = false; resolve() }
169 const timeout = setTimeout(release, 5000)
170 releaseWorkspace = () => { clearTimeout(timeout); release() }
171 })
172 }
156173 const response = await next()
157174 status = response?.status ?? null
158175 if (delayStart && request.method === 'POST' && pathname.endsWith('/workspace/execution') && response?.ok) { delayStart = false; await new Promise<void>(resolve => { releaseStart = resolve }) }
159 if (request.method !== 'GET' || !/\/workspace\/execution\/[a-f0-9-]+\/events$/.test(pathname) || !response?.ok || !response.body) return response
160 streamStarts++
176 const executionEvents = /\/workspace\/execution\/[a-f0-9-]+\/events$/.test(pathname), workspaceEvents = pathname.endsWith('/workspace/events')
177 if (request.method !== 'GET' || !(executionEvents || workspaceEvents) || !response?.ok || !response.body) return response
178 if (executionEvents) streamStarts++
161179 const reader = response.body.getReader()
162180 let closed = false, output: ReadableStreamDefaultController<Uint8Array> | undefined
163181 const close = async () => { if (closed) return; closed = true; output?.close(); await reader.cancel().catch(() => {}) }
164 closeStream = close
182 if (executionEvents) closeStream = close
183 else closeWorkspaceStream = close
165184 // Opaque native chunks pass unchanged. Only the private fixture can end a connection.
166185 const body = new ReadableStream<Uint8Array>({
167186 start(controller) { output = controller },
@@ -188,7 +207,7 @@ route.use(async (request: Request, next: () => Promise<Response | null> | Respon
188207})
189208const page = () => new Response(html, { headers: { 'content-type': 'text/html', 'cache-control': 'no-store' } })
190209route.get('/incidents', page)
191for (const action of ['status', 'diagnostics', 'release-start', 'arm-before-return', 'before-return', 'release-and-renew', 'before-admission', 'verify-admitted', 'read-only', 'revoke']) route.get(`/__fixture/${action}`, control)
210for (const action of ['status', 'diagnostics', 'release-start', 'arm-before-return', 'before-return', 'release-and-renew', 'before-admission', 'verify-admitted', 'release-workspace', 'read-only', 'revoke']) route.get(`/__fixture/${action}`, control)
192211const server = await route.serve({ hostname: '127.0.0.1', port: 0, nativeRoutes: false })
193212if (process.env.EXECUTION_BROWSER_EVIDENCE) { await mkdir(process.env.EXECUTION_BROWSER_EVIDENCE, { recursive: true }); await writeFile(join(process.env.EXECUTION_BROWSER_EVIDENCE, 'compiled.html'), html) }
194213await writeFile(join(root, 'execution-credentials.json'), JSON.stringify({ url: `http://127.0.0.1:${server.port}`, key: seeded.key, sourceDigest: seeded.source.digest, token: fixture.senderToken, control: secret }), { mode: 0o600 })
@@ -197,8 +216,8 @@ try {
197216 assert.equal(await child.exited, 0, 'Isolated real execution browser driver must pass')
198217}
199218finally {
200 releaseStart?.(); releaseCredit?.()
201 await closeStream?.(); await server.stop(true)
219 releaseStart?.(); releaseCredit?.(); releaseWorkspace?.()
220 await closeStream?.(); await closeWorkspaceStream?.(); await server.stop(true)
202221 const slot = executionOwner().slot as { execution: string, binding: { scope: string }, producer: string, worker: Worker | null } | null
203222 if (slot?.producer === 'pending') {
204223 const core = await import('../../../resources/functions/drone/public-safety/execution/service')
tests/helpers/execution-browser-driver.tsmodified+28-3
Changes to tests/helpers/execution-browser-driver.ts
@@ -1,5 +1,5 @@
11import assert from 'node:assert/strict'
2import { mkdir, readFile } from 'node:fs/promises'
2import { mkdir, readFile, writeFile } from 'node:fs/promises'
33import { basename, join } from 'node:path'
44import { startWorkspaceBrowser } from './workspace-browser'
55import { settleExecutionDiagnostics } from './execution-diagnostics'
@@ -41,6 +41,7 @@ async function failureDiagnostics() {
4141 workspaceStatus: selected('[data-workspace-status]', ['disconnected', 'connecting', 'synchronizing', 'current', 'reconnecting', 'refused']),
4242 executionPhase: selected('[data-execution-phase]', ['no current run', 'waiting-for-consumer', 'running', 'stopping', 'completed', 'canceled', 'failed', 'discarded']),
4343 hasExecutionId: !!document.querySelector('[data-execution-id]'), hasCompletion: !!document.querySelector('[data-execution-completion]'),
44 hasSelectedSource: !!document.querySelector('[data-workspace-source]'),
4445 startDisabled: start ? start.disabled === true : null, admitDisabled: admit ? admit.disabled === true : null,
4546 hasSourceExists: !!document.querySelector('[data-execution-source-exists]'), hasExecutionError: !!document.querySelector('[data-execution-error]')
4647 };
@@ -53,7 +54,9 @@ async function failureDiagnostics() {
5354 admissionRequests: diagnosticPage ? diagnosticPage.requests.filter(request => request.method === 'POST' && request.url.endsWith('/workspace/execution/admission')).length : null,
5455 }
5556 const text = JSON.stringify({ ...base, ...parts })
56 console.error(Buffer.byteLength(text, 'utf8') <= 8192 ? text : JSON.stringify({ ...base, server: { available: false }, dom: null, byteBudgetExceeded: true }))
57 const bounded = Buffer.byteLength(text, 'utf8') <= 8192 ? text : JSON.stringify({ ...base, server: { available: false }, dom: null, byteBudgetExceeded: true })
58 console.error(bounded)
59 await writeFile(join(evidence, 'failure-diagnostics.json'), `${bounded}\n`, { mode: 0o600, flag: 'wx' })
5760 }
5861 catch { console.error(JSON.stringify({ label: 'execution-browser-failure-diagnostics', phase, available: false })) }
5962 finally {
@@ -130,10 +133,32 @@ try {
130133 await first.screenshot(join(evidence, 'execution-completed-mobile.png'), 375, 900)
131134 assert.equal(await first.evaluate('Math.max(0, document.documentElement.scrollWidth - innerWidth)'), 0, 'Execution UUID and digest wrap at375px')
132135 mark('explicit source admission')
136 await first.evaluate(`(() => {
137 const probe = { samples: [], overflow: false };
138 const sample = () => {
139 const value = document.querySelector('[data-workspace-source]')?.textContent.trim();
140 const selected = !value ? 'absent' : value === ${JSON.stringify(data.sourceDigest)} ? 'original' : 'other';
141 if (probe.samples.at(-1) === selected) return;
142 if (probe.samples.length >= 64) { probe.overflow = true; return; }
143 probe.samples.push(selected);
144 };
145 const observer = new MutationObserver(sample);
146 observer.observe(document.body, { childList: true, characterData: true, subtree: true });
147 sample(); globalThis.executionSourceProbe = { probe, stop: () => observer.disconnect() };
148 })()`)
133149 await first.click('Admit completed source')
134150 await first.wait("!!document.querySelector('[data-execution-source-exists]')", 'Explicit admission must refresh actual source catalog', 15000)
135151 await control('verify-admitted')
136 assert.equal(await first.evaluate("document.querySelector('[data-workspace-source]')?.textContent.trim()"), data.sourceDigest, 'Admission cannot select its new source')
152 mark('fresh workspace after admission renewal')
153 assert.equal(await first.evaluate("!!document.querySelector('[data-workspace-source]') || !!document.querySelector('[data-execution-completion]')"), false, 'Native renewal must clear private panes before fresh authorization')
154 await control('release-workspace')
155 await first.wait(`document.querySelector('[data-workspace-status]')?.textContent.trim() === 'current' && !!document.querySelector('[data-execution-source-exists]') && document.querySelector('[data-workspace-source]')?.textContent.trim() === ${JSON.stringify(data.sourceDigest)}`, 'Fresh authorization must restore the original selection after admission', 15000)
156 const selections = await first.evaluate<{ samples: string[], overflow: boolean }>('(() => { globalThis.executionSourceProbe.stop(); return globalThis.executionSourceProbe.probe; })()')
157 assert.equal(selections.overflow, false, 'The complete bounded selection history must be available')
158 assert(selections.samples.includes('absent'), 'The actual native renewal must hide selected imagery')
159 assert.equal(selections.samples.at(-1), 'original')
160 assert(selections.samples.every(value => value === 'original' || value === 'absent'), 'Admission must never select the new source, including during renewal')
161 await writeFile(join(evidence, 'admission-renewal.json'), `${JSON.stringify(selections)}\n`, { mode: 0o600, flag: 'wx' })
137162 assert.equal(await first.evaluate("document.querySelector('#incident-note')?.value"), 'Later unsent observation survives execution success')
138163 mark('read-only credential')
139164 const { token } = await control('read-only')