Skip to main content
Doyel Labs

Engineering

When the software does not know, it does nothing.

One rule holds together every product Doyel Labs ships. The thing that can spend money — cash, a wage, a share — lives on your machine, and the thing we run in the cloud cannot spend it. Everything below follows from that.

Rule 1

Fail closed.

An unknown value blocks an action rather than filling it in. Nothing here has a fallback that pretends. If the wage determination for a contractor's county is not on SAM.gov, the draft is refused. If a broker quote is stale, the entry is not placed. If a Space code has expired, the join call returns permission-denied. An outage should look like an outage.

Payroll

A day rate below the SCA floor blocks the draft. Every stub carries the floor line.

BAI

A stale quote, a missing account snapshot, an unknown earnings date each block an entry; chat cannot spend.

ConnectionLoop

Firestore and Storage rules default-deny. A member row is created only against a live invite code.

Rule 2

Local-first for anything that can move money.

A cloud breach cannot reach a broker account we cannot see. Broker credentials for BAI stay in Windows Credential Manager. The device holds the arm phrase; we hold none of them. On the payroll side, we store the operator's records — but we do not hold their bank routing or account numbers, and we do not move their money.

BAI

Broker keys and access tokens live on the operator's machine, encrypted where the OS allows. Never sent to Doyel Labs.

Payroll

Bank routing and account numbers are not stored. The operator pays through their own bank; the software prepares the pay run.

ConnectionLoop

Sessions live in the OS keychain (Keychain / Keystore). The on-device state cache is AES-256-GCM sealed under a per-install key.

Rule 3

Updates are signed and refused mid-trade.

No one, including us, can push code to your desk that we did not sign with a key baked into the app. An update is refused while the desk is armed or holding a position. The website ships as static assets on Cloudflare Pages; there is no runtime we can push mutations to.

BAI

Signed with a key baked into the app. Refused while armed or holding a position.

Website

Static export, immutable per deploy on Cloudflare. `_headers` bans third-party scripts on marketing pages.

Rule 4

Structured logs, redacted at the source, one row per action.

Log lines carry ids, counts, and durations — not content. A redaction pass in CI drops any field that looks like a secret or a wage. Every state change worth reading a year later becomes an audit row: a sign-in, a rate change, a passkey enrolment, an armed session, a blocked stub. Rows export to CSV.

Payroll

Paystub, WD lookup, SCA-block, contractor-rate change, email delivery — all logged with actor and detail. 180-day retention.

BAI

Sign-in, device change, billing event, staff action. Structured logs with a redaction pass tested in CI.

ConnectionLoop

Callables log ids, counts, codes, durations — never content. Crash notes are scrubbed twice.

Rule 5

Tests pin the paths a subtle regression could break.

Chat cannot spend

Pinned by tests, not by policy. Four code paths originate an order in BAI and each checks the entitlement, the arm phrase, and the kill switch.

SCA floor is enforced

The stub renderer refuses to produce a stub whose day rate does not clear the WD floor for the county.

Rules v2 is exercised

ConnectionLoop's Firestore + Storage rules run against `rules-tests/` on the emulator. A rules change without a green run is not shipped.

Kill disarms, never sells

A kill switch pull disarms and blocks new orders. It never sells a position out from under a customer.

Subscription failure is not a cliff

A lapsed payment stops new entries and keeps managing exits on positions the desk already opened.

Update refused while armed

The updater checks armed state and holding state before applying.

The company decision

Say what the software does not do, in the same voice.

Doyel Labs LLC is not a broker-dealer, an investment adviser, a bank, a payroll processor, a professional employer organization, a money transmitter, or a reporting agent. None of the software above holds customer money or securities. We ship one company. We say the same thing everywhere.

Source of truth · BAI-Desk/website/src/app/security/page.tsx · ConnectionLoop/docs/SECURITY.md · index/netlify/functions/payroll.js