Architecture example · sideload access · v1.0 · 2026-11-14

Example Project Architecture · Sideload Access

Only two roles are built in: the scheduler (control plane) and the development machine (execution plane). Developers, testers, support staff, CI jobs, scripts and external systems are not containers or registered instances — each holds a sideload token (sdl_…) and calls device → control plane → this host's root scheduler → development machine. A device never learns the scheduler address and holds no instance credential. Host boxes stay generic — workspace, agent runtime, console commands and resource admission — with no project-specific operations.

简体中文
Access side: one device + one sideload token — no container, no instance registration Developers sdl_… · tasks:write · console:run Testers sdl_… · tasks:write · tasks:read CI / other systems sdl_… · scoped API calls Support / customers sdl_… · tasks:read/write HTTPS · Authorization: Bearer sdl_… Task scheduler (control plane) Built-in · single state authority · tokens stop here Sideload entry (PCS) Bearer sdl_ · scope check Resolve host root scheduler Task API POST /api/v1/tasks State + idempotency key State machine QUEUED → ASSIGNED → RUNNING trace_id end to end Queue & dispatch Pull + heartbeat · capability Lease · timeout · retry File channel Attachments in · artifacts out SHA-256 · byte-for-byte PostgreSQL · audit Single source of task state Token create / delete logged Task dispatch · heartbeat (Pull) Execution plane · built-in development machines Every host exposes the same generic surface — no project-specific operations are shown. Development machine 01 host-runtime · workspace · Isolated task workspace · Agent profile / Shell · Console commands (scope) Built-in · generic host Development machine 02 host-runtime · workspace · Isolated task workspace · Agent profile / Shell · Console commands (scope) Built-in · generic host Development machine 03 host-runtime · workspace · Isolated task workspace · Agent profile / Shell · Console commands (scope) Built-in · generic host Scale out · ×N add development machines · Same task / lease path · Same admission rules · Same artifact channel The only built-in execution role File channel · attachments and artifacts · Development machines write results to their own workspace · The scheduler collects them into the artifact channel · Clients download with tasks:read · no direct host access · SHA-256 verified · returned byte-for-byte Attachments travel the other way: upload to the task, then read by the development machine. Sideload systems · not built-in Same task API · same scopes · same audit — no containers, no heartbeats, no leases CI / build jobs sdl_… · tasks:write · Submit / cancel tasks · Read builders & queue · Collect artifacts Test automation sdl_… · tasks:write · Submit test tasks · Poll status · Download artifacts Internal portal / tickets sdl_… · tasks:read/write · Create tasks · Show queue state · Link artifacts Scripts / CLI sdl_… · scoped token · One-off jobs · Automation · Same HTTPS path Boundary: no container · no instance row · no heartbeat · no lease · token stored as a hash · unknown scopes rejected Sideload client view One token, one host HTTPS · scope checked at the control plane · POST /api/v1/tasks · GET /api/v1/tasks/:id · POST .../attachments · GET .../artifacts Never sees the scheduler address Customer / third party curl · scripts · scoped token same sideload path Host network policy · outbound only Development machines · no inbound Dependency access · no instance credentials Host resources & protection Admit before start · resource state independent of task state · single host Host Resource Monitor built-in · short-interval sampling · CPU / memory / disk / I/O · Container health · PIDs Resource admission controller host / control / storage / headroom · Atomic: budget + concurrency · Shortfall → QUEUED, no container Protection watchdog host-watchdog.service · independent · Missed heartbeat → PROTECTING · Close admission · alert Resource admission before claim Overload stages independent of task state NORMAL Normal scheduling WARNING Fewer slots · light first THROTTLED Pause high-resource tasks PROTECTING Close admission · protect PG RECOVERING Observe, then ramp up Support plane (internal) Scheduler / development machines only · sideload clients never attach · all internal Artifact store reports / attachments · SHA-256 PostgreSQL task state authority · audit Redis queue hint · rebuildable LLM gateway provider mapping · quota Secret Store references · no plaintext Monitoring metrics · logs · dashboards
Legend Sideload access (device → control plane) Task dispatch / heartbeat (Pull) File channel (attachments / artifacts) Host network policy (outbound only) Resource admission / watchdog Sideload boundary (not built-in)
① Hold a sideload token→ ② Submit a task→ ③ Scope check→ ④ Scheduler queues / dispatches→ ⑤ Development machine runs→ ⑥ File channel collects→ ⑦ Client downloads artifacts

Exactly two built-in roles

The platform has a scheduler and at least one development machine. Developers, testers, support staff, CI jobs, scripts and external systems enter through sideload tokens, so no new role, container or dispatch rule is introduced for them.

One fixed call chain

A device calls the control plane; the control plane validates the token, resolves the host and its root scheduler, and forwards the request. The device never sees the scheduler address and never holds an instance credential — the same path the admin app uses.

A sideload is not an Agent

It has no container, no registration, no heartbeat and no lease of its own. Because it reuses the normal task / lease / fencing path, it cannot bypass scheduling, admission or auditing.

Hosts stay generic and scale out

Every development machine exposes the same surface: an isolated workspace, the bound Agent Profile or Shell, console commands within scope, and resource admission before start. Scaling means adding hosts, not defining new roles or project-specific operations.

Least privilege by construction

Scopes are a closed set: tasks:read, tasks:write, builders:read, queue:read and console:run. console:run is granted separately from tasks:write, and unknown scopes are rejected rather than ignored.

Files move both ways

Inputs are uploaded as attachments and land under <workspace>/attachments/. Outputs are collected through the scheduler's artifact channel: any format, SHA-256 verified and returned byte-for-byte instead of being packed into stdout.