Architecture
The graph, the ledger and the runbook language, and how much of each exists.
This page is for the person a CISO forwards the deck to. Three architectural decisions carry the product: a per-tenant operations graph that tracks its own staleness, an append-only ledger anchored outside our control, and a runbook language whose type system bounds what an agent can touch.
Two of the three are designs, not running code. Every claim below carries a build status and a specification reference. Implemented means running code with a runtime path. Partial means some of it runs and the gap is named. Specified means a committed design with nothing behind it yet.
Deployment
The shape of the system.
Multi-tenant SaaS in two regions, with the tenant boundary enforced at the storage layer and the signing keys held by the tenant. Private cloud is a v2 commitment and air-gapped deployment is deferred, along with the on-prem inference it would require. Neither is on offer in the first release.
Multi-tenant SaaS, per-region clusters
SpecifiedOne codebase, per-region clusters, starting with us-east-1 and eu-west-1. EU residency is a first-release requirement rather than a later region expansion, because half the target segment cannot buy without it.
Spec §11.1, D10
Tenant pinned to a region at provisioning
SpecifiedResidency is set when the tenant is created and is not a per-record routing decision. Ledger anchors are written per region. APAC is deferred unless a top-tier customer funds it.
D14
Per-tenant logical isolation
PartialAn organisation model and tenant-scoped authentication run today in auth-service. Schema-per-tenant is not in place, and the query-layer enforcement that makes cross-tenant joins impossible by construction is not finished.
Spec §4, §8.5
Per-tenant key custody for ledger signing
SpecifiedEach tenant's chain is signed under a key that tenant custodies. StaidKit never holds root keys, which also means key loss is a customer-side failure with a documented runbook rather than something we can silently paper over.
Spec §11.1, §11.5
Operational memory
A graph that shows you where it is stale.
Services, assets, incidents, runbooks, actions, controls, evidence, people, teams, vendors and deployments in one per-tenant graph, joined by edges the runbook compiler computes blast radius from and the agents retrieve over. Both read the same substrate, which is why provenance has to travel with the data rather than sit in a sync log.
Neo4j is wired and holds a small part of this. The graph traversal API and the freshness reconciliation pass are not built.
Spec §8.6, §4Every node and every edge carries four fields
- source
- Which system asserted this: the CMDB, telemetry, or a person. A dependency Datadog observed and a dependency someone typed into ServiceNow in 2023 are not the same claim and are not stored as though they were.
- last_verified_at
- When the assertion was last confirmed by its source, not when the row was last written. Those two timestamps diverge constantly, and only the first one tells you whether to trust the edge during an incident.
- confidence
- The weight the reconciliation pass gives this assertion when sources disagree. It is also what an agent has to cite when it reasons over the edge.
- provenance_ledger_entry_id
- The ledger entry that recorded the assertion, so a graph fact traces back to the action that produced it.
Reconciliation, and the disagreement
Ingestion is event-driven from the CMDB, observability, deploys and cloud config. A reconciliation pass runs hourly per service. When sources disagree, the most recent telemetry-confirmed value wins, and the disagreement is written into the graph as its own node so an operator can act on it.
Spec §8.3
Why staleness is on the screen
The standing complaint about every CMDB is that it says “synced” and is wrong. A dependency graph you cannot date is not a safety control, because a blast radius computed from an unattributed edge is a guess with a number next to it. The design makes staleness queryable, and an agent that finds stale data on a Tier-0 service is required to abstain rather than reason over it.
Spec §8.3, §7.3
Action ledger
One entry rule, and an anchor you hold.
Every state change, agent decision, approval, execution and evidence artefact appends one entry to a per-tenant chain. The rule is the whole mechanism, and it is short enough to check.
There is no hash-chain code in the product. The chain on the homepage is a demonstration of this rule written into the marketing site, not the ledger.
Spec §9, §4entry_hash = H( prev_hash ‖ canonical(payload) ‖ signed_at ‖ signer_kid )
prev_hash entry_hash of seq-1; the first entry uses 64 zeros
canonical(payload) {"key":"value",...} in declaration order, no whitespace
signed_at RFC 3339, as recorded by the signer
signer_kid identifier of the per-tenant signing keyCanonical serialisation is part of the format, not an implementation detail. Field order and the absence of incidental whitespace are fixed, because a verifier written by someone else has to reach the same bytes we did. Alter entry N and its hash changes, so it no longer matches the prev_hash that entry N+1 committed to, and every entry after it fails in turn.
The homepage record is computed with exactly this rule, using SHA-256, in the reader’s browser, over the bytes on the page. The production algorithm is still an open sub-decision: the specification proposes Ed25519 signatures over a BLAKE3 chain.
Spec §5.8, §9.1
The chain on its own proves internal consistency, which is not the property an auditor needs. We hold the database, so we could in principle rewrite the whole chain. Anchoring is what closes that gap. The per-tenant chain root is written hourly to a transparency log the customer controls.
Tampering with StaidKit’s own database is then detectable by the customer using only their own anchor records. The audit export is a chain segment, the entities it references, the control mappings and the anchor records. The verifier is intended to be open source, so an auditor runs it against the export and reaches a conclusion without trusting us.
Spec §9.2, §9.4
What this is not
It is not a blockchain. There is no consensus protocol, no distributed validator set, no token, nothing to do with web3. It is a tenant-scoped, append-only, hash-chained log with external anchoring. The engineering is moderate. The operational burden of running it correctly for years is the hard part, and that is where the value is.
Spec §9.6
When the anchor is unreachable
The chain keeps writing locally, the segment is marked unanchored, an alarm is raised, and the segment is backfilled when the log is reachable again. An operator can see which range of their own history is currently unanchored rather than discovering it during an audit.
Spec §11.5
Runbook language
A model can be trusted to emit a typed program. It cannot be trusted to emit shell.
Runbooks are typed programs, statically verified before they can run. The type system is what makes generated automation reviewable, because the reviewer checks a signature rather than reading a script for what it might touch.
No language, compiler or parser exists in the repository. This is greenfield.
Spec §10, §4Every action declares its signature
- Inputs and outputs, typed.
- Side effects, as the set of service types the action can touch.
- Preconditions, written as predicates over graph state.
- Rollback, as a typed inverse action, or an explicit irreversible marker. A step with neither does not compile, and irreversible raises the approval required.
- Required approvals, as a predicate on the blast-radius class.
- Cost, estimated and typed by unit.
Spec §10.1, §10.3
Blast radius is computed twice
Once from the graph at static verification, and again from the graph at dispatch. The two are separate because the graph moves in between: a service that had no dependents when the runbook was written may have four by the time someone runs it at 3am. The author never declares the class. Required approvals scale by it.
| Class | Scope |
|---|---|
| contained | A single resource. One pod, one cache key, one certificate. |
| service | One service and everything the graph says depends on it. |
| environment | Environment-wide. Every service in staging, or every service in production. |
| tenant_global | Crosses environments. DNS failover and equivalent changes land here. |
Spec §10.2
The design intent is narrow and worth stating plainly. A foundation model asked for Bash produces something a reviewer has to read line by line to work out what it can reach. The same model asked for a typed program produces something whose reach is bounded by the type system and computed from the graph, and programs that fail verification go back to the model with the type errors as context instead of to a human as a judgement call.
Spec §10.4, §10.6
Model governance
No agent has a direct path to production state.
Model choice is a tenant policy rather than a platform default, and every privileged tool call leaves the agent, routes through the policy engine, and waits for a human.
There is no agent framework and no model provider wiring in the repository.
Spec §7, §4Multi-provider, routed per tenant
A per-tenant routing policy selects the model and the provider. The committed default is Anthropic Claude, with a heavier model reserved for high-stakes decisions and OpenAI as fallback. The top tier brings its own keys, so inference happens under the customer’s account and contract. On-prem inference arrives with air-gapped deployment in v2, and not before.
D15
The governance gate
Anything privileged, meaning a write to production state, an external communication, or an evidence export, routes through the policy engine and an approval. Tools with side effects are runbook invocations rather than raw API calls, so the type system and the blast-radius computation apply to agent actions exactly as they apply to human ones. Every tool call and every retrieval set is recorded in the ledger.
Spec §7.1, §8.4
Data stores
What is wired, and what the design still needs.
Three of the seven stores the architecture calls for are not connected to anything yet. Two of those three are load-bearing for the graph and the agents, which is a fair summary of why those capabilities are marked specified rather than partial.
| Store | Status | Where |
|---|---|---|
Postgres Transactional state: organisations, users, incidents, runbooks, controls, evidence, actions, agent decisions, ledger entries. | Implemented | wired |
Redis Cache, ephemeral state, on-call rotation cursor. | Implemented | wired |
Kafka Event ingestion and fan-out to the telemetry, asset and crisis services. | Implemented | wired |
Neo4j The operations graph. Running, and carrying a small fraction of the schema above. | Partial | wired, underused |
TimescaleDB Telemetry-derived edge weights and time-series metrics. The graph cannot compute freshness from telemetry without it. | Specified | not wired |
Object store Evidence artefacts, audit packets, runbook execution logs. | Specified | not wired |
Vector store Per-tenant namespace for semantic retrieval. The agents read from this. | Specified | not wired |
Spec §11.2, §4
Targets
Numbers we have committed to and have not measured.
These are design targets from the specification. None of them is a benchmark result, and for the subsystems marked specified above there is nothing yet to benchmark.
| Path | Design target, not a measured result |
|---|---|
| Event ingestion API | p95 under 150ms |
| Action dispatch after approval, including the ledger write | p95 under 5s |
| Ledger write added to dispatch | p95 under 10ms |
| Audit packet export, 90-day range | p95 under 60s |
| Assets per tenant at general availability | 100,000 |
| Cross-region failover | RPO under 5min, RTO under 30min |
Targets, Spec §11.3
The ledger figure is the one that shapes the design. Holding the write to ten milliseconds on the dispatch path is what lets the chain be extended synchronously with the action rather than reconciled afterwards, which is the difference between a record and a log that mostly agrees with what happened.
Design partner programme
The conversation starts with the specification, not a demo.
If you have read this far you are the person we want in the room. We will walk the entry rule, the anchoring model and the runbook type system with your architects, and we expect to be pushed on the parts that are still designs.