Trust
Security
Nodus is the infrastructure execution layer for AI workloads. Customer-visible state (workloads, events, ledger, artifacts) is durable, tenant-isolated, and recoverable. This page describes what the system enforces today, not what we intend.
We are in pilot. No SOC 2, no ISO certification, no third-party penetration test, no external security assessment, and no claim to any of them. Where a control is pilot-stage rather than production-grade, it says so.
Controls in place
- Auth. Two credentials, kept apart. Machines send a bearer API key, hashed at rest with SHA-256. People sign in to the console with an email and a bcrypt-hashed password and receive an expiring session token, which is refused on the endpoints that issue and revoke keys.
- Tenant isolation. Enforced at the API layer: every read and write is scoped to the tenant on the authenticated credential.
- Roles. Admins manage people, keys, and spend limits; members submit work and read it back. Enforced server-side, and an account cannot be left without an admin.
- Spend ceiling. An optional monthly cap per account. A submission that would cross it is refused with
402before anything is planned or reserved. - Audit. Console actions record the actor: keys issued and revoked, people added, removed and re-roled, invitations, and limit changes.
- Checkpoint integrity. SHA-256 verified on commit; a digest mismatch fences the generation instead of storing a bad checkpoint.
- Generation fencing. At most one generation writes durable progress per stage.
- Webhooks. HMAC-SHA256 signatures over timestamp and body (
X-Nodus-Signature) with a replay window. - Ops. Reclaim and recovery endpoints require
NODUS_OPS_TOKENon top of tenant auth, and are refused outright when no token is configured. - Brand lock. Customer routes expose Nodus catalog SKUs only.
Data in transit
API, console, and this site are HTTPS only. Runner traffic (heartbeats, checkpoint prepare, commit, open) uses the same TLS endpoints as the customer API.
Site and console send Strict-Transport-Security with a two-year max-age, includeSubDomains, and preload, so a browser that has seen us once never falls back to plaintext. Responses also set X-Content-Type-Options: nosniff, X-Frame-Options: DENY, a referrer policy, and a permissions policy denying camera, microphone, and geolocation. Private routes under /n/ add no-store and noindex.
The pilot has no private networking, VPC peering, IP allowlisting, or customer-managed encryption keys. Data at rest sits in managed Postgres and object storage under the provider’s encryption, not a key you hold. If diligence requires any of it, tell us before you sign. We would rather scope it than imply it.
Credentials
API keys are bearer credentials. Treat one as a password for your tenant. Anything done with it is attributed to you.
- Hashed at rest. We store a SHA-256 hash and a short non-secret prefix. We never store the raw key.
- Shown once. The raw key comes back only in the response that issues it. We cannot recover it or show it again. A lost key is replaced by revoking and reissuing, never by lookup.
- Revocable, with optional expiry. Keys can carry an expiry and can be revoked at any time; either way they fail closed on the next request. During an incident we can revoke every live key for a tenant in one action. In the pilot that is an operator action: email the address below and we cut it.
- Last use is recorded. Each key keeps a throttled last-used timestamp, so a key that should be dormant is visible when it is not.
- Browser handling. The console never holds an API key. Signing in exchanges an email and password for a session token, and that token is what lives in
sessionStorage, dies with the tab, and expires after twelve hours. A key appears in the browser exactly once, in the response that creates it. The privacy policy covers what else the console stores.
Tenant isolation
Every authenticated request resolves the bearer key to a principal, a tenant ID and a key ID, before any handler runs. Workload, event, ledger, artifact, webhook, and billing handlers then scope every read and write to that tenant. Asking for another tenant’s workload by ID is a miss rather than a leak: the record is never in scope to return.
Signup is invite-gated and never lets a caller choose their tenant. Identifiers are assigned by Nodus with random entropy, a request supplying one is rejected, and an existing identifier is refused rather than joined. Probing tenants that are not yours violates the Terms. Report the hole instead; see disclosure below.
People join an existing tenant only by redeeming an invitation issued by one of its admins. The invited address is taken from the invitation, never from the request that redeems it, so one link cannot become an account for a different email. Invitations are single-use, expire in 72 hours, and are stored as a hash. Password reset tokens work the same way over two hours, and consuming one signs out every session that account already had.
Checkpoint integrity
A checkpoint is only useful if you trust it enough to restart from it. Every object in a manifest carries a SHA-256 digest, and on commit the control plane verifies each against the bytes it actually holds before accepting the manifest.
A mismatch rejects the commit and fences the generation. That is deliberate. A corrupt checkpoint is worse than a missing one, so recovery falls back to the last manifest that verified.
Generation fencing backs this up. Prepare hands out a fencing token and commits from a superseded generation are refused with a conflict, so at most one generation writes durable progress per stage even when a reclaimed machine comes back late.
Webhook signing
Webhook requests carry X-Nodus-Timestamp and X-Nodus-Signature. The signature is the hex HMAC-SHA256 of the timestamp, a period, and the exact raw body, keyed with the endpoint secret. Verify against raw bytes; re-serializing the JSON first will not match.
Comparison is constant-time, and any timestamp more than five minutes from now is rejected regardless of signature, which bounds replay. Inbound supplier events are also deduplicated on X-Nodus-Event-Id and capped at a 1 MB body. On your side: verify before you parse, and treat a delivery you have seen as a no-op.
Reporting a vulnerability
Report to nodus.infrastructure@gmail.com with what you did, what you saw, and the tenant ID you used. Time-sensitive findings should say so in the subject line.
We acknowledge within three business days, return a triage result and fix plan within ten, and tell you when it ships. No bounties during the pilot. We will credit you by name if you want it.
Good-faith research is welcome and we will not pursue legal action over it. To stay in good faith: test only your own tenant, stop at proof, and do not exfiltrate, alter, or destroy data. No denial-of-service, load testing, spam, or social engineering of our team or vendors. Give us reasonable time to fix before disclosing.