softwerkBook a factory walkthroughSign in

a software factory with a certificate on every build

Agents write the change.
The proof ships with it.

Softwerk is a software factory for engineering teams that have to show how code was built, not only that it works. An issue in Linear starts a mission. Role-typed agents plan, build and review it on your own model credential and your own GitHub App installation.

Everything the fleet publishes is screened for identifiers first, a separate model reviews the work, and the build is recorded on a content-addressed certificate archived write-once for six years, beside an evidence bundle your auditor can check offline.

screened before publicationreviewed by a separate modelone certificate per treewrite-once, six yearsone sealed credential per taskGitHub App and Linear application not yet seeded on production
sha256(tree)
the certificate key

One certificate per file tree. The id is the hash of the certificate's own canonical body and the key is the hash of the tree, so a changed byte anywhere is a different certificate, and a tree already certified is reused rather than re-minted.

2190 days
COMPLIANCE mode

Certificates are archived in an S3 Object Lock bucket in COMPLIANCE mode with a six-year default retention. The mode cannot be downgraded, the retention cannot be shortened, and the worker's role has no delete on the bucket.

1 credential
per task, sealed

The fleet holds no tenant secret at rest. Each task asks for exactly one credential over a signed request bound to tenant, mission, role and purpose, and receives it sealed for single use.

0 merge rights
held by the merger

The role chain ends at merger, and merger cannot merge. A person on your team merges the pull request. Deployer and observer are never triggered by the chain.

How a mission runs.

Assign an issue to Softwerk in Linear, or mention it in a comment, and a mission starts: one pipeline row and one outbox row written in the same transaction, so a mission is either dispatched or does not exist. Seven roles then hand the work down the line; the chain stops at merger, which holds no merge rights, and deployer is never triggered by the chain.

Every role posts what it did as a comment on the issue with a link to the run and to the full report, so the ticket never leaves Linear. A mission that dies before it starts, or goes silent, is failed by a sweeper and says so on the run page and in the audit log rather than hanging.

issue
Linear
prd
builder model
planner
builder model
architect
builder model
executor
builder model
verifier
separate model
compliance
separate model
merger
separate model
merged by
a person

scroll sideways for the whole chain

builds

prd

writes the requirement from the issue

builds

planner

breaks it into ordered tasks

builds

architect

shapes the change against the repository

builds

executor

writes the code, with tests, and opens the pull request

reviewsseparate model

verifier

reviews the diff on a separate model

reviewsseparate model

compliance

runs the compliance checklist against the diff on a separate model

reviewsseparate model

merger

default-deny gatekeeper: recommends or refuses the merge, holds no merge rights

outside the chainnever auto-triggered

deployer

refused as a resume target

outside the chainnever auto-triggered

observer

refused as a resume target

Guardrails, by name.

Five controls on a fleet mission. Each carries a status: what runs on every build, or a switch with the flag that flips it and its production value. The full list, with what each switch changes and where the code lives, is on the guardrails page.

Publication screen

every build

Every word the fleet publishes outside your account, issue titles, run reports, failure comments, pull request bodies, goes through a local Presidio screen first. A detection, a timeout or a malformed answer withholds the text and publishes a value-free reference to the mission instead. The screen is not behind a switch, and the fleet logs entity types and counts, never values.

Separate-model review

every build

The reviewing roles, verifier, compliance and merger, run on a different model from the builder: reviewed by a separate model, not a separate vendor. Both are Anthropic models: claude-sonnet-4-6 reviews what claude-opus-4-8 wrote. A role never reviews its own work, and the fleet certificate does not record which model reviewed.

Human gates

switchFACTORY_GATES_ENFORCE1

Three gates are declared once in .softwerk/factory.yaml and pinned to code by test: approve the plan before any code is written, answer a question any role stops to ask, decide the merge with the pull request open. Gate rows, pause, resume and decisions are live in the web app and the worker.

on today Set to 1 on production since 2026-09-14 on web, worker and agents. Every mission stops after architect until a person approves the plan; a role that asks keeps no checkout and opens no pull request until it is answered; merger stops with the pull request open until a person decides the merge, and a person still merges. Only a decision through the API or from Linear (a state change, a reaction, a threaded reply) resumes a stopped run. An undecided plan gate expires after 24 hours and releases the repository. Every decision is an audit row, and the stored question is sealed under the tenant's key.

No unattended merge or deploy

every build

The role chain ends at merger and merger cannot merge. Deployer and observer exist in the roster and are refused as resume targets. Production itself is released by a person dispatching a workflow with an explicit image tag; nothing deploys on a push or a tag.

Certificate scan

every build

After a mission completes, a sweeper reads the pull request's head tree from GitHub, runs the HIPAA, SOC 2 and HITRUST control sets over the whole tree and mints one certificate per tree with the per-framework results and a fail-closed verdict. Whether the team waits for the certificate before merging is the team's own rule.

Every check runs. The certificate is a record.

On a fleet mission every review and gate runs and is recorded, and on a completed mission every scan runs and is recorded. The certificate is minted after the mission completes and refuses nothing: no switch in the tree turns a failed fleet verdict into a refused pull request today, and a person merges. One switch changes what a mission does, the three human gates, and it is on. Four more govern the generation and deploy path the factory inherited, which a mission never passes, and are off. What each switch changes and where the code lives are on the guardrails page.

on a fleet mission: the one switch that changes what a mission does
switchoffonproduction
FACTORY_GATES_ENFORCEweb, worker and agentsthe chain runs without stopping; gate rows, pause and resume exist in the web app and the worker, and no row is openedevery mission stops after architect until a person approves the plan, a role that asks stops until it is answered, and merger stops with the pull request open until a person decides the merge; a person still merges1
inherited generation and deploy path: enforced on no mission path, never passed by a mission
switchoffonproduction
COMPLIANCE_VETO_ENFORCEweb and workerthe compliance verify on a generated build is disclosure-only: the result is recorded and nothing is withhelda failed verify withholds the generated build0
PHI_GUARD_ENFORCEweb and workerevery file write and tool result of a generated build is scanned, observe-only: detections are evented and nothing is blockeda write carrying a high-precision identifier (SSN, MRN, card number, email, phone) is blocked0
REVIEWER_ENFORCEweb and workerthe reviewer of a generated build is advisory: the verdict is recorded and never blocksa block verdict, or independence that cannot be proven, fails the generation; revise still ships0
VERIFICATION_GATE_ENFORCEweb and workerthe verification gate at the generation ship boundary and on the project deploy route is a no-opa failed certificate refuses the ship or deploy0

scroll sideways for the production column

The certificate.

A mission that completes earns a VerificationCertificate; a mission whose merge a person refuses is failed and earns none. Its id is the sha256 of its own canonical body, so an edited field is a different id. It is keyed on the sha256 of the file tree: one certificate per tree. It carries the tree hash, the commit, a roll-up verdict that fails closed, the per-framework results for the HIPAA, SOC 2 and HITRUST control sets that run on every scan, disclosed warnings, an evidence report of finding counts, the issuer, the mint time and the expiry.

A sweeper mints it from the pull request's head tree after the mission completes. It does not carry source code, and it does not carry the name of the model that reviewed the diff. Minting is fail-closed: without the archive bucket the verifier returns nothing and no certificate exists, and a refusal is written on the run as a fixed skip reason you can read on the run page.

  • packages/compliance/src/verification/certificate.ts
  • apps/web/prisma/schema.prisma VerificationCertificate
  • apps/worker/src/fleet-certificate-sweeper.ts status completed
  • apps/web/src/lib/factory/mission-gate-ingest.ts (a refused merge writes failed)
  • apps/worker/src/fleet-certificate.ts FLEET_SKIP_REASONS
  • apps/worker/src/ship-verification-provider.ts

The archive an auditor opens.

Certificates are archived into an S3 Object Lock bucket in COMPLIANCE mode with a 2190-day default retention. COMPLIANCE mode cannot be downgraded to GOVERNANCE and the retention cannot be shortened; the worker's role may put an object and set its retention and has no delete. In the app, one page renders a certificate and one renders the mission's full report, and every Linear activity links to both.

Evidence exports as a deterministic bundle of canonical bytes, signed with a detached ed25519 signature when the deployment holds a signing key, which production does not today: a production export is unsigned and says so. A zero-dependency script checks the bundle offline, with no network and without cloning any repository: it recomputes every certificate's content address, verifies the signature when there is one and fails the run on an unsigned bundle, saying why, and it duplicates the canonicalisation on purpose, because a verifier that needs the thing it verifies is not independent. Underneath, the audit log refuses UPDATE and DELETE at the database, and gate review decisions are append-only with segregation of duties and justified overrides.

Read the evidence page

Your credential runs your mission, or the mission does not run.

Your Anthropic API key runs your missions, and Softwerk never resells inference. A tenant with nothing connected gets one activity on the issue saying the mission did not start: no repository claim, no model run. Your GitHub App installation opens the pull request with a token minted per task and scoped to the one repository the mission names, so GitHub itself refuses a repository you did not install on. Your Linear workspace keeps the ticket.

The fleet never holds a tenant secret at rest. Per task it asks for exactly one credential over a request signed with an HMAC bound to tenant, mission, role and purpose, and receives it sealed under AES-256-GCM with an HKDF-derived key and a single-use nonce held in a Redis replay store; in production the broker refuses without it. The run page says which credential each mission ran on.

How bring your own works

Regulated industries are the proof point. Every engineering team is the market.

The gate was built for patient-facing and life-science software, where a release has to carry its own evidence. HIPAA, SOC 2 and HITRUST control sets run on every scan. ISO 27001, GxP, 21 CFR Part 11 and PCI-DSS are registered control sets and are not live: no fleet certificate carries their result today. If your security review asks who reviewed the AI's code, whether a person approved the change, and whether you can prove both a year later, the answer is the same certificate, the same audit row and the same offline-verifiable bundle. None of those mechanisms knows what industry you are in; only the profile changes.

Healthcare, life science, finance, public sector, consumer, and everyone else

For the platform team.

tenant isolation
Every query runs through a tenant-scoped client, and Postgres row-level security sits behind it on the factory tables as defense in depth: enabled, not forced, so it binds non-owner roles. (apps/web/src/lib/tenant-context.ts; apps/web/prisma/migrations/20260901000000_factory_tenant_rls)
secrets
Credentials are envelope-encrypted at rest and never returned to the browser. Whether a connection exists is read from the table, never cached. (apps/web/src/lib/tenant-credential.ts; apps/web/src/lib/onboarding-substrate-state.ts)
pod isolation
Inside the executor pod the model subprocess runs as a second uid with an allowlist of environment variables and no route to instance metadata. The fleet's own IAM role holds its lease table, its queues and send-only on the progress queue. (apps/agent/src/uid-split.ts; apps/agent/src/executor.ts LLM_ENV_ALLOWLIST; cdk/lib/agent-fleet.ts)
storage and transit
Aurora is encrypted at rest with deletion protection, daily backups with a cross-region copy, and a restore drill on record. Application connections verify the RDS certificate bundle and the cluster requires TLS; the shared cache requires authentication. (cdk/lib/aurora-stack.ts; cdk/lib/backup-stack.ts; cdk/config/environments.ts auroraForceSsl, sharedCacheAuthRequired; docs/runbooks/database-tls.md; docs/runbooks/cache-auth-and-worker-iam.md)
release
Production is a manual workflow dispatch with an explicit image tag; nothing deploys on a push or a tag. Rollback is a dedicated workflow dispatched with the previous tag. Every action in the deploy and rollback workflows is pinned to a commit SHA, and those workflows authenticate to AWS by OIDC rather than long-lived keys. (.github/workflows/cd-softwerk-prod.yml; .github/workflows/rollback-softwerk-prod.yml; cdk/lib/oidc-stack.ts)
logs
Error events are scrubbed of identifiers in Sentry's beforeSend where a Sentry DSN is configured, which the production worker does not have today, and the fleet pod's logger redacts credential paths (token, apiKey, privateKey, password, authorization) before a line reaches stdout. (apps/worker/src/sentry.ts beforeSend; apps/agent/src/logger.ts redact)

Asked before the first call.

Ten questions, answered against what the product does today, each with the files that back the answer.

Who pays for the model, and does Softwerk see the key?

You do, on your own Anthropic API key: Softwerk never resells inference, and the key is envelope-encrypted at rest and never returned to the browser. Per task the fleet asks for exactly one credential over an HMAC-signed request bound to tenant, mission, role and purpose and receives it sealed for single use, so the fleet holds no tenant secret at rest; every run page says which credential it ran on and what each role turn cost, and there is no spend cap, so your Anthropic console is the cost control.

  • apps/web/src/lib/fleet/issue-credential.ts
  • apps/agent/src/credential-broker.ts
  • apps/web/src/lib/tenant-credential.ts
  • apps/worker/src/mission-cost.ts (a record, not a charge)

What blocks a merge today?

A person: the role chain ends at merger, merger holds no merge rights, and a person on your team merges the pull request. Every review and gate on a fleet mission is recorded and every scan on a completed mission lands on a certificate that refuses nothing: no switch turns a failed fleet verdict into a refused pull request today, and the one switch that changes what a mission does, FACTORY_GATES_ENFORCE, stops the mission for a human decision and is 1 on production since 2026-09-14 on web, worker and agents.

on a fleet mission

  • FACTORY_GATES_ENFORCE1

inherited generation and deploy path, never passed by a mission

  • COMPLIANCE_VETO_ENFORCE0
  • PHI_GUARD_ENFORCE0
  • REVIEWER_ENFORCE0
  • VERIFICATION_GATE_ENFORCE0
  • apps/agent/src/roles.ts ROLE_CHAIN
  • apps/worker/src/fleet-certificate.ts (minting is not enforcement)
  • apps/worker/src/fleet-certificate-sweeper.ts status completed
  • k8s/overlays/softwerk-prod/kustomization.yaml lines 159 to 187 and 291 to 319
  • cdk/config/environments.ts factoryGatesEnforce

Is the reviewer independent?

The work is reviewed by a separate model, not a separate vendor: claude-sonnet-4-6 reviews what claude-opus-4-8 wrote, both Anthropic models, and the verifier, compliance and merger roles are marked independent in the roster, so no role reviews its own work. The fleet certificate records the verdict and not the reviewer, a person decides the merge, and REVIEWER_ENFORCE, in the same overlay, governs the inherited generation path and is 0 on production.

  • apps/agent/src/executor.ts BUILDER_MODEL, REVIEWER_MODEL
  • apps/agent/src/roles.ts independent flag
  • apps/worker/src/fleet-certificate.ts mint input
  • apps/worker/src/reviewer-enforce.ts
  • apps/worker/src/pipeline-consumer.ts

What does an auditor receive?

A certificate per file tree, keyed on sha256(tree), carrying the commit, a fail-closed verdict, the per-framework results for the HIPAA, SOC 2 and HITRUST control sets, disclosed warnings, the issuer, the mint time and the expiry, archived in an S3 Object Lock bucket in COMPLIANCE mode for 2190 days, above an audit log whose UPDATE and DELETE the database refuses and gate review decisions that are append-only with segregation of duties. An evidence bundle exported as canonical bytes, signed with a detached ed25519 signature when the deployment holds a signing key, which production does not today, and a zero-dependency script that checks it offline, with no network and without cloning any repository, and fails its run on an unsigned bundle while still checking every certificate's content address.

  • packages/compliance/src/verification/certificate.ts
  • cdk/lib/worm-bucket.ts
  • apps/web/src/lib/evidence/sign-bundle.ts not_configured
  • scripts/verify-evidence-bundle.mjs
  • apps/web/prisma/migrations/20260412_audit_log_immutability/migration.sql
  • apps/web/src/lib/gate-review/service.ts

Which frameworks run?

HIPAA, SOC 2 and HITRUST run on every scan and their results land on the certificate; ISO 27001, GxP, 21 CFR Part 11 and PCI-DSS are registered control sets with their own scanners and are not live, because the fleet passes no profile, so no fleet certificate carries their result today. Softwerk holds no SOC 2, HITRUST or ISO 27001 attestation of its own; a scan result is evidence about your build.

  • packages/compliance/src/verify.ts DEFAULT_VERIFY_FRAMEWORKS
  • apps/worker/src/fleet-certificate.ts runComplianceVerify(files, {})
  • packages/compliance/src/frameworks/registry.ts

Does PHI leave our account?

The factory is not a business-associate context and handles no PHI by design, Softwerk signs no BAA, and a mission runs on your own Anthropic API key, clones with your own GitHub App installation token scoped to the one repository named, and writes back to your own Linear workspace. For the case where an issue, a report or a pull request body carries identifiers anyway, everything the fleet publishes is screened by a local Presidio sidecar and withheld on a detection, a timeout or a malformed answer, error events are scrubbed of identifiers in Sentry's beforeSend where a Sentry DSN is configured (the production worker has none today), and the fleet pod's logger redacts credential paths before a line reaches stdout; nothing screens the executor's file writes inside a mission, because the worker's write screen (PHI_GUARD_ENFORCE) runs on the inherited generation path, is 0 on production, and puts no PHI-guard result on a fleet certificate.

  • apps/agent/src/phi.ts PUBLICATION_BLOCK_TYPES
  • apps/agent/src/runner.ts screenForPublication
  • apps/agent/src/redact.ts
  • apps/worker/src/sentry.ts beforeSend
  • apps/agent/src/logger.ts redact
  • apps/worker/src/phi-guard-screening.ts (imported by apps/worker/src/consumer.ts alone)
  • SOFTWERK.md, Two compliance surfaces

How does the team supervise a mission?

From Linear: assign an issue to Softwerk or mention it in a comment, each role posts what it did on the issue with a link to the run and to the full report, and the three gates declared in .softwerk/factory.yaml (plan, question and merge) take a decision from a state change, a reaction on the gate's own comment, a threaded reply or a call to the API, with an undecided plan gate expiring after 24 hours and releasing the repository. Stopping a mission at those gates is the FACTORY_GATES_ENFORCE switch, 1 on production since 2026-09-14 on web, worker and agents: every mission stops after architect until a person approves the plan, and merger stops with the pull request open until a person decides the merge.

  • apps/web/src/lib/linear/gate-events.ts
  • apps/agent/src/tracker.ts
  • apps/agent/src/gates.ts FactoryGateCheck
  • apps/worker/src/sweeper/config.ts:90
  • docs/runbooks/mission-gates.md

Can we run it in our own account, or air-gapped?

Not today: the whole stack runs in Softwerk's AWS account. Deployment into your account through the same infrastructure code is planned and not live, and so are AWS Bedrock roles, federated identity and multi-key pools with failover.

  • cdk/ is the whole stack

We are not regulated. What do we get?

The same certificate: a security review of agent-written code asks who wrote it, who reviewed it, who approved it and whether you can show all three a year from now, and the run names every role and the credential it ran on, a separate model reviews every build, a person merges the pull request, and one certificate per tree is archived write-once for six years and exported as a bundle a reviewer checks offline. SOC 2's change-management control asks for exactly this trail and the SOC 2 control set runs on every scan regardless of industry; none of those mechanisms knows what industry you are in, only the compliance profile changes.

  • apps/agent/src/roles.ts
  • apps/web/src/components/factory/run-detail.tsx Ran on
  • packages/compliance/src/verify.ts DEFAULT_VERIFY_FRAMEWORKS
  • cdk/lib/worm-bucket.ts

Can we sign up today?

Not self-serve: sign-in is Google SSO on an allowlisted workspace domain, a workspace is set up by Softwerk on request to hello@softwerk.io, and model spend runs on your own key with pricing beyond that agreed per workspace. The GitHub App and the Linear application are configured once for the whole deployment, not per workspace, and on production today the Linear values are empty placeholders and the GitHub App private key is a placeholder, so no Linear connect step is offered and no mission can clone a repository or open a pull request until both are seeded.

  • apps/web/src/lib/auth-options.ts
  • apps/web/src/lib/github-app-install.ts isGitHubAppConfigured
  • apps/web/src/lib/linear/config.ts isLinearConfigured
  • docs/runbooks/linear-agent.md step 2
  • docs/runbooks/fleet-credentials.md

Connect a repository, a Linear team and an API key. Keep everything else.

Softwerk is not self-serve: sign-in is Google SSO on an allowlisted workspace domain, and a workspace is set up by Softwerk on request. The GitHub App and the Linear application are configured once for the whole deployment by Softwerk, not per workspace, and the app offers each connect step only when that deployment-level configuration is in place. On production today the Linear application is not yet seeded, so its connect step is not offered, and the GitHub App private key is a placeholder, so no mission can clone a repository or open a pull request yet. Once both are seeded, you connect your Anthropic key, your GitHub App installation and your Linear team, and the first mission ends in a pull request with its certificate beside it.

Book a factory walkthrough