CHANGELOG
Shipping log
What we built, when we built it. Newest first. Material breaking changes are flagged in bold.
October 2026 · Workspace: customer keys
- Hold the key yourself. Put TillSecrets, TillForge or TillArk under a key in your own AWS KMS, Google Cloud KMS or Azure Key Vault. TillDev asks your cloud each time it needs the data and stores no credential for it; revoke the key and that product goes offline until you give it back. Customer keys.
- You choose how long an opened key stays in memory: 5, 10 or 15 minutes. Only owners can put a product under a key, after seeing what goes offline and approving it.
- Each key is checked every 6 hours, and owners are emailed when it starts refusing or is set to be deleted.
- Dashboard: Customer keys in workspace settings. CLI:
tilldev customer-keys(next CLI release). API:/api/org/customer-keys, in/openapi.json; calls that need a locked product answer423 KEY_LOCKED. - TillAuth and TillCache too. TillAuth can go under a key once you confirm, by typing a phrase, that your users can’t sign in while it refuses. TillCache under a key seals every namespace at the edge: values, hash values, set and sorted-set members, queue and pub/sub messages, with data already stored sealed in the background. Commands that need the plain value, such as
INCRandAPPEND, are refused in a sealed namespace. Sealed namespaces. - TillPulse too. Under a key, the full detail of every event is sealed: stack frames, local variables, breadcrumbs, device and user context. Events are sealed at the edge as they arrive, with a hybrid post-quantum key (X-Wing), and uploaded source maps, dSYMs and ProGuard mappings are sealed in storage. Issue titles, counts, charts, search and questions keep working while the key refuses; events that arrive meanwhile are held, sealed, for up to seven days. Sealed event detail.
- Every dashboard call and page that touches a locked product now answers
423with the kind of refusal, or503when your cloud doesn’t answer, instead of a server error.
October 2026 · TillShield: insider risk
- TillTell rules for your own members and service credentials: mass clones, repositories made public, push mirrors, secret reveal and delete bursts, detections weakened and guardrails turned off, and credentials doing something new. A score per person that is a reason to look, never a verdict. Insider risk.
October 2026 · TillShield: compliance evidence
- Evidence for SOC 2, ISO/IEC 27001 and NIST CSF assessments from what your products already record: thirty controls judged over a period, attestations for evidence held elsewhere, and monthly snapshots in a hash chain an auditor can verify without TillDev. Evidence, not an assessment. Compliance.
October 2026 · TillShield: threat intel
- Tor exits, addresses other workspaces flagged, and known-exploited CVEs on findings and in the vulnerability inventory, from feeds whose licences allow it and patterns no workspace is named in. Threat intel.
October 2026 · TillShield: engagements
- Purple-team exercises, red-team runs and pentests from a plan an owner authorises to a report for your auditor: plays judged against what TillTell saw from the tester networks, private links for outside testers, findings in the vulnerability inventory, and retests. Engagements.
October 2026 · TillShield: vulnerability disclosure
- A public program for security researchers, with policy, scope, safe harbor, rewards and security.txt, and an inbox that keeps reports sealed and tracks your reply and decision promises. Vulnerability disclosure.
October 2026 · TillShield: vulnerabilities
- One inventory across the scanners, with a due date per level, owners, accepted risk with an end date, an overdue alert and mean time to fix. Vulnerabilities.
- Fix pull requests that upgrade a vulnerable dependency in npm, pnpm, yarn, pip, Go and Cargo lockfiles, and the command to run where a lockfile can't be changed safely.
October 2026 · Workspace: data policy
- Decide what is kept and what leaves. For contact details, payment data, government ID numbers and IP addresses, choose per channel whether they are kept, masked or, for AI, refused: stored events, alerts, issue trackers, webhooks and AI. Credentials are always masked. Data policy.
- Your own patterns. Up to 10 regular expressions for customer numbers and other data only you know the shape of, each masked as a named marker. They run in linear time, so none can slow ingestion down.
- Every AI request passes the policy: the assistant, questions about your data, grounded answers and TillMind. A request holding a class you block is refused before anything is sent. TillMind's own analysis of new issues can be turned off, and What reached AI lists every hand-off that masked or refused something, across products.
- User ids that look like an email address, phone number or IP address are now stored as a stable stand-in unique to your workspace. Counts of affected users still work.
- Masking no longer mistakes UUIDs and long hex ids for phone, card or ID numbers or IP addresses, in our SDKs and on our side.
- Dashboard: Data policy in the workspace sidebar, with a preview and counts of what each channel caught. CLI:
tilldev data-policy. API:/api/org/data-policyand/api/org/ai-egress, in/openapi.json.
October 2026 · TillAuth: SSO session
- Sign in once per browser. A sign-in on the hosted pages now carries to the app's other clients on that browser until it idles out (7 days), reaches its limit (30 days from the real sign-in) or the sign-in behind it ends. Each reuse is scored for risk. On by default; turn it off or change the limits on the Policies page. SSO session.
- Sign in with TillAuth gains
prompt=noneandid_token_hintlogout, and itsend_session_endpointmoves to the hosted pages; the old address redirects. CLI:tilldev auth apps update --sso-session. API:/v1/sso/*, in/openapi.json.
October 2026 · TillAuth: risky sign-ins
- Session risk now scores sign-ins, against where each user has signed in lately. On
enforcean unusual sign-in owes a second factor, or a code we email, and a very unusual one is blocked with a reset link sent to the user; passkeys are never blocked. At sign-in. - Hosted pages,
@tillstack/auth-react0.3 and Till Authenticator handle the emailed code. API:POST /v1/signin/email-code, in/openapi.json.
October 2026 · TillAuth: groups
- Groups from Entra ID, Okta and OneLogin over SCIM, or made by hand. Your apps read them from the
groupsclaim, and internal-app rules can let a whole group in. Groups. - Dashboard: a Groups page on each identity app, and groups on each user. CLI:
tilldev auth groups. API:/api/auth/admin/apps/<app>/groups, in/openapi.json.
October 2026 · TillAuth: internal apps
- Your own tools behind your sign-in, without changing them. Admin panels, dashboards and staging sites sit behind the proxy you already run (nginx, Caddy, Traefik, Envoy or a Cloudflare Worker), or behind
tilldev auth access proxy, which asks TillAuth about every request. Internal apps. - Rules per path: who may pass, by address, domain or role, and whether they need a second factor, a sign-in from the last few minutes, a low-risk session, or a request from given networks or countries. A simulator answers what a draft would do before you save it.
- The app receives the person's identity as headers, plus a signed assertion bound to its host that
@tillstack/auth-node0.5 verifies withcreateAccessVerifier. - Dashboard: Internal apps on each identity app, with filled-in proxy configuration and a decision log. CLI:
tilldev auth access. API:/api/auth/admin/apps/<app>/access, in/openapi.json.
October 2026 · Workspace: access review
- Who can do what, in one place. The access review lists owners and admins without an authenticator, people who have gone quiet, a workspace that doesn't require a second factor, too many admins, a single owner and self-approved time-boxed admin. Access review.
- Credentials across every product. API keys and TillSecrets, TillForge, TillCache, TillArk, TillNotary and TillShield credentials that are unused, outlived the person who made them, or can write and never expire.
- Each finding comes with the change that fixes it. Keep one on purpose with a reason for up to a year; it comes back when that runs out. The thresholds are yours to set.
- Role changes, removals from the workspace and changes to the two-factor requirement are now in the audit log, so moving someone into owner or admin raises a finding in TillTell. Time-boxed admin can no longer turn the two-factor requirement off.
- Dashboard: Access review in the workspace sidebar. CLI:
tilldev access review, with--fail-onfor scheduled checks. API:/api/access/review, in/openapi.json.
October 2026 · Workspace: time-boxed admin
- Admin for a task, then back. Owners and admins choose which developers and viewers may ask and for how long, from 15 minutes to 8 hours. They ask with a reason and a ticket, someone else approves, and their session holds admin until the window closes. Time-boxed admin.
- An elevation can't keep itself. While elevated, nobody can grant or remove admin, invite admins, change who may ask, approve requests, turn approvals off or change company sign-in. API keys, service tokens and agent tokens never elevate.
- A window ends on its own, early from the Access page or the CLI, or when the person's role changes, they leave, their eligibility is removed or a TillShield playbook signs them out. Every step is in the audit log.
- Dashboard: Access in the workspace sidebar, with a banner while elevated. CLI:
tilldev access. API:/api/access/elevationsand/api/access/eligibility, in/openapi.json.
October 2026 · TillAuth: session risk
- Every refresh is scored against the session's own history: a different browser or system, a new country, impossible travel, a different network and addresses TillGate lists. Watch the scores, or have the app's policy ask for a fresh sign-in or end every session of the user. Session risk.
- Ending a session from the dashboard, the CLI, a TillShield rule or a playbook now stops its access tokens at their next check instead of after up to 10 minutes.
- Dashboard: country and risk on the Sessions pages and a Session risk policy on each app. CLI:
tilldev auth sessionsandtilldev auth apps update --session-risk. API:/api/auth/admin/apps/<app>/sessions, in/openapi.json.@tillstack/auth-react0.3 addsstate.reason.
October 2026 · TillSecrets: workload SVIDs
- Workloads prove who they are to your own services. Give a workload identity a SPIFFE path and it can ask for a short-lived JWT-SVID naming the services that should accept it. Each workspace is its own trust domain, with a public SPIFFE bundle, a JWK set and an OpenID discovery document. Workload SVIDs.
- X.509-SVIDs for mutual TLS. The workload makes its own key pair and gets a certificate naming its SPIFFE ID, signed by the workspace's own CA, for 5 minutes to 24 hours.
tilldev secrets svid x509 --out <dir> --renewkeeps the certificate, key and CA bundle fresh on disk;client.x509Svid()does it in code. The CA is published asca.pemand in the bundle. - The signing key and CA stay in the vault. They are minted there, stored encrypted, rotate every 30 days and can be distrusted at once. Rotating and distrusting wait for approval.
- Check one anywhere.
SvidVerifierandverifyX509Svidin@tillstack/secrets-node0.5.0 andtilldev secrets svid verify(with--certfor X.509) check the signature, trust domain, audience, expiry and which SPIFFE IDs you allow. - Dashboard: the SPIFFE path on each identity and the Workload SVIDs panel under Secrets → Identities. API:
/api/secrets/svidandPOST /v1/svidand/v1/svid/x509, in/openapi.json. CLI:tilldev secrets svid,svid x509and--svid-path.
October 2026 · TillForge: IaC scanning
- Misconfigurations caught in the commit that writes them. Terraform, CloudFormation and Kubernetes files at every pushed commit are judged by the same checks cloud posture runs on live accounts: public buckets, open ports and databases, unencrypted storage, missing backups and logs, privileged containers and roles that grant everything. IaC scanning.
- Answered from the file, or not at all. A value known only at deploy time leaves that check unanswered and listed, never guessed. Templates are listed as not read rather than rendered.
- Warn, block merges, or block deploys. Each commit gets a
tilldev/iaccheck, and a new deploy policy check can refuse a deployment with a finding at your IaC bar. Accepting a finding is audited and follows the resource. - Dashboard: TillForge → IaC scanning and the repository Findings tab. API:
/api/forge/repos/:repo/iac-scansand/api/forge/iac/*, in/openapi.json. CLI 0.10.0:tilldev forge iac.
October 2026 · TillShield Posture: checks, findings and drift
- Every resource judged on every sync against a library of checks for AWS, Google Cloud, Azure, Cloudflare, DigitalOcean and your TillDev workspace. Failing checks open findings that resolve on their own once fixed, and a check that couldn’t read what it needs is counted as not run, never as a pass. Checks and findings.
- Alert, report or off for each check, and exceptions with a reason and an end date for a risk you keep.
- Drift from a baseline, field by field, until you accept the new settings.
- Dashboard: Shield → Posture. API: findings, policies, exceptions, drift and baseline, in
/openapi.json. CLI:tilldev shield posture findings.
October 2026 · TillForge: source track
- Every protected-branch update, graded and signed. TillForge records the rule in force each time a covered branch moves, grades it against the SLSA Source track, and signs source provenance and a verification summary for the commit with P-256 and ML-DSA-65. Source track.
- A deploy check for verified source, warn by default, and a Source column in the supply chain map.
- Dashboard: the repository Source tab. API:
/api/forge/repos/:repo/source, in/openapi.json. CLI:tilldev forge source, whoseverifyworks offline.
October 2026 · TillForge: deploy gates and supply chain coverage
- Approvals that hold. A deploy TillForge runs to an environment that needs approvals waits until other people approve it, owners or admins on production. Deploys, promotions and rollbacks to such environments now wait, and a new deployment starts as
waiting. Deploy gates. - A deploy policy. Dependencies, secrets, code findings and signed provenance of the deployed commit, each off, warn or block.
- Supply chain map. Which checks cover each repository's default branch, and what a failure stops. Supply chain.
- Dashboard: TillForge → Supply chain and the repository Deploy tab. API:
/api/forge/deploy/policy,/api/forge/supply-chain/coverageand deployment approvals, in/openapi.json. CLI:tilldev forge deploy approveandtilldev forge coverage.
October 2026 · TillForge: build provenance
- Signed SLSA provenance for every CI build. When a job that declares outputs goes green, TillForge signs an in-toto statement of the commit, workflow, runner, image and the sha256 of each output, with your workspace's key in TillSecrets, using both ECDSA P-256 and ML-DSA-65. Build provenance.
- Levels you can trust. Each record shows its SLSA build level and what stands before the next; a release takes the lowest level of the builds behind its assets.
- Dashboard: TillForge → Provenance and the repository Artifacts tab. API:
/api/forge/provenance/*and/api/forge/repos/:repo/artifact-records/:id/provenance, in/openapi.json. CLI 0.10.0:tilldev forge provenance, whoseverifyworks offline.
October 2026 · TillForge: code scanning
- Security flaws in your source, on every push. Fifteen rules read JavaScript and TypeScript, Python, Go, Java, Kotlin, Swift and Dart, plus Android and iOS app config, for injection, switched-off TLS and token checks, unsafe deserialisation, weak crypto, credentials in plain app storage, cleartext traffic and open WebViews. Each names its CWE and its OWASP Top 10 and MASVS categories. Code scanning.
- Warn or block. Each commit gets a
tilldev/sastcheck. Warn, the default, passes and lists findings; block fails it and refuses merges into protected branches while a finding at your chosen severity or above is active. Accepting a finding is audited and lasts until that line changes. - Dashboard: TillForge → Code scanning and the repository Findings tab. API:
/api/forge/repos/:repo/code-scansand/api/forge/sast/*, in/openapi.json. CLI 0.10.0:tilldev forge sast.
October 2026 · TillForge: secrets in every file
- Scans of a commit's files. Every file at the default branch, each green build and each release is read for secrets, not only what a push changed, and each commit gets a
tilldev/secretscheck. Scans of a commit's files. - TillDev credentials are detected at push and in scans, and new TillAuth refresh tokens start with
tau_rt_so they can be. - Dashboard: the repository Findings tab. API:
/api/forge/repos/:repo/secret-scans, in/openapi.json. CLI 0.10.0:tilldev forge secrets.
October 2026 · TillForge: known vulnerabilities
- Every SBOM checked against OSV. TillDev mirrors the OSV advisory database and checks every commit's dependencies against it, hourly, without sending package lists anywhere. Each commit gets a
tilldev/scacheck. Vulnerabilities. - Block mode gates merges. Merges into protected branches are refused while a fixable vulnerability at or above your chosen severity, or a known malicious package, is present. Exceptions name a reason and expire within a year.
- Dashboard: TillForge → Vulnerabilities and the SBOM tab. API:
/api/forge/vulnerabilitiesand/api/forge/sca/*, in/openapi.json. CLI 0.10.0:tilldev forge vulnsandtilldev forge sca.
October 2026 · TillDrill: exposure scans of your cloud addresses
- See what your own addresses answer on. An exposure scan opens a TCP connection to each of 105 well-known ports on one public address, reads what the service announces, reads the certificate where the port speaks TLS, and closes. It reports the ports that answered, which belong on an internal network, what appears to be running, certificates that are expired, self-signed, weak or for another name, exchanges that carry credentials in the clear, and what opened or closed since the last scan. How exposure scans work.
- The cloud account is the proof. Addresses come only from the cloud accounts you connect under Posture, never from something typed in. An address arrives with scanning off, is retired when the account stops holding it, and is scanned only while the account has confirmed it in the last 7 days — read again before a single connection is made.
- Your own rules, next to what answered. The rules in the account that open a port to the whole internet are read from the account and lined up against what actually answered: a port answering with no rule that opens it, and a rule opening a port with nothing behind it. No payload, no credential, nothing changed; one scan makes at most 140 connections, 8 at a time, and stops after 4 minutes.
- Dashboard: Shield → TillDrill → Exposure. API:
/api/shield/drill/exposure, in/openapi.json. CLI 0.10.0:tilldev shield drill exposure sweepandtilldev shield drill exposure scan <address-id> --wait.
October 2026 · TillDrill: intrusive probes, opt-in
- Find where your own target mishandles input. Intrusive probes send values built to be parsed wrong — a stray quote, a value a template engine would evaluate, an over-long field, a sign-in that must fail — and read the answer for a leaked database error, an evaluated marker, a server fault, or a session that isn’t locked down. They are the one part of TillDrill that reaches the target this way, so they stay off until you turn them on. How intrusive probes work.
- Three gates before a single request. They need the file served on your target (not a DNS record or a domain verified elsewhere), your recorded authorisation that you may test it (which lapses after 90 days), and a maintenance window you set — a weekday, a start time and a length, read in your timezone. A run outside every window is refused, and only one intrusive run happens at a time across the workspace.
- Inert by design. Nothing written, nothing deleted, no real password guessed, and no real account touched — the failing sign-ins only ever use a reserved username that can never exist. The values sent are the smallest that reveal mishandling, never a working exploit, and a run touches at most 6 pages and 20 parameters, one request at a time, so it is never a load test. One run sends at most 240 requests and stops after 5 minutes; Stop ends it within seconds and keeps what it saw.
- CLI 0.10.0:
tilldev shield drill targets intrusive <target-id> onrecords your authorisation,window addsets a window, andtilldev shield drill intrusive <target-id> --waitruns one inside an open window.
October 2026 · TillDrill: safe active checks
- Ask your own target directly, and read only. An active run asks for a short fixed list of paths that leak by accident, reads whether a folder lists its files, reads the methods the target states and whether TRACE answers, asks what it shares with another origin, tests whether a link parameter sends visitors off-site, reads DNS for a name pointing at a provider that no longer claims it, and looks up public advisories for the version the target names. How active checks work.
- Nothing is written. No PUT, DELETE, PATCH or CONNECT is ever sent, no credential is guessed, and no request carries a payload meant to change behaviour. The origin used to ask about cross-origin sharing and the host used to test redirect parameters are both reserved names that cannot resolve, so a target that honours the redirect sends nobody anywhere real.
- Gated on the proof, and off by default. Active checks need the file on your server, or a DNS record over https. They are off for every target until you turn them on, so an upgrade never starts them on a target proven for passive checks alone. One run sends at most 160 requests, 4 at a time, and stops after 3 minutes; Stop ends it within seconds and keeps what it saw.
- Judged like the rest. 15 checks tagged with their OWASP Top 10 category, each with how to fix it. A part that could not run is reported as not run, never as a pass. A path counts as leaking only when its body matches what that file looks like and differs from the page the target serves for anything missing, and an advisory match is shown as a fingerprint, not proof.
- CLI 0.10.0:
tilldev shield drill active <target-id> --waitruns them and exits 1 on a failing check at medium or above;tilldev shield drill targets active <target-id> dailysets the schedule.
October 2026 · TillForge: SBOMs
- Every dependency of every build. Each successful CI build, release and push to the default branch now gets a software bill of materials, read from the lockfiles committed at that commit across twelve ecosystems, and downloadable as CycloneDX 1.6. SBOMs.
- Find a package across repositories. TillForge → Dependencies, or
tilldev forge deps <package>, shows which repositories use a package and whether their default branch still does. - Dashboard: an SBOM tab on each repository. API:
/api/forge/repos/:repo/sbomsandGET /api/forge/dependencies, in/openapi.json. CLI 0.10.0:tilldev forge sbom,sbomsanddeps.
October 2026 · TillForge: artifact records
- Trace a file to the build that made it. Every successful CI job and every release now leaves a record of its commit, its builder and the sha256 of each output. List a job’s outputs under
artifacts:in.tillforge/ci.ymland the runner hashes them after the job’s container exits. Artifact records. - Releases link to their builds. A release records each asset that has a sha256 and links to the CI builds whose outputs match, whichever came first. Records stay when the job, release or repository is deleted.
- Breaking: a job that lists
artifactsneeds an upgraded runner. An older runner claiming one fails it with a reason rather than passing it with nothing recorded. - Dashboard: the repository’s Artifacts tab, which also hashes a file you choose in the browser without uploading it. API:
GET /api/forge/repos/:repo/artifact-records,/artifact-records/:idandGET /api/forge/artifact-records?digest=, in/openapi.json. CLI 0.10.0:tilldev forge artifacts,showandverify <file>, which sends only the digest and exits 1 when no recorded build produced the file.
October 2026 · TillDrill: defense drills
- Prove a rule still fires. A defense drill replays a TillTell rule’s own smallest test that fires into your security stream, then times how long TillTell takes to record the finding and how long the playbook it suggests takes to finish. Start one under Shield → TillDrill → Defense drills. How defense drills work.
- Kept apart from real traffic. Drill events are signed by Till, and one that claims to be a drill without the signature is handled as real. They are correlated on their own, so they can’t set off or hide a real detection. Their findings never alert, and every playbook step they start is simulated.
- Proven on the coverage map. A detected drill marks the rule’s ATT&CK techniques as proven for 90 days, for the rule version it drilled. Changing the rule takes the proof away until it is drilled again.
- CLI 0.10.0:
tilldev shield drill defenselists the rules that can be drilled and when each was last proven;defense <rule-id> --waitprints the times and exits 1 when nothing detected the drill.
October 2026 · Posture: DigitalOcean teams
- Connect DigitalOcean with a read-only token. Make a personal access token with seven read scopes in the team you connect, and add the connector with the team’s UUID. The token is sealed in TillSecrets as it arrives, and each sync stops if the token belongs to another team. Connect DigitalOcean.
- What it reads. Droplets with public addresses, backups and the cloud firewalls that guard them (or that none do); firewall rules open to the internet; managed databases any address can reach; Kubernetes clusters without auto-upgrade or a control plane firewall; and load balancers that take plain HTTP without redirecting.
- Every listed provider is now live. TillDev, AWS, Google Cloud, Azure, Cloudflare and DigitalOcean. A scope left off the token makes its type partial and names the scope; Spaces buckets aren’t read, since the API can’t list them with a token.
October 2026 · Posture: Cloudflare accounts
- Connect Cloudflare with a read-only token. Cloudflare has no identity federation, so its connector reads with an Account API token you create with six read permissions, listed on the connector and in the docs. The token is sealed in TillSecrets as it arrives, shown only by its last four characters, and destroyed when you disconnect. The first sync starts at once and stops if the token answers for another account. Connect Cloudflare.
- What it reads. Whether the account enforces two-factor sign-in, members without it and super administrators; the account’s API tokens that can write, cover every resource, have no IP limit or no expiry; each zone’s SSL mode, Always Use HTTPS, minimum TLS, HSTS, DNSSEC and records that aren’t proxied; and R2 buckets with a public r2.dev address or custom domain.
- Honest about gaps. A permission left off the token makes its type partial and names the permission to add. A token Cloudflare no longer accepts fails the sync and says to replace it, which Shield → Posture and
tilldev shield posture tokendo in place. - CLI 0.10.0:
tilldev shield posture add cloudflare --account <id> --token-stdin; without a token on a terminal it lists the permissions and asks for it hidden.trust <id>andproviderslist the permissions.
October 2026 · Posture: Azure subscriptions
- Connect Azure with no client secret. Add a connector with the subscription, tenant and the client ID of an app registration, then give the app a federated credential naming that one connector and the Reader role on the subscription. Each sync signs in to Microsoft Entra ID with a five-minute TillDev token and checks the subscription is in your tenant before it reads. Shield → Posture shows the credential and the Azure CLI commands filled in. Connect Azure.
- What it reads. Who holds Owner, Contributor and User Access Administrator on the subscription, custom roles that allow every action, Defender for Cloud plans and activity log export; storage accounts, network security groups, virtual machines and their public addresses, Azure SQL servers with their firewall rules and auditing, and key vaults.
- Honest about gaps. A resource provider that isn’t registered leaves its type empty and is listed on the subscription. A refused sign-in says which part of the trust is wrong.
- CLI 0.10.0:
tilldev shield posture add azure --account <subscription> --tenant-id <id> --client-id <id>,trust <id> --out .writes the federated credential, andtenantandclientchange the app in place.
October 2026 · Posture: Google Cloud projects
- Connect Google Cloud with no service account key. Add a connector with the project id and the workload identity provider that trusts it, then create the pool and provider with TillDev’s connector issuer and an attribute condition naming that one connector, and grant its principal read access. Each sync exchanges a five-minute TillDev token for a fifteen-minute access token. A service account to act as is optional. Shield → Posture shows the steps and the gcloud commands with your project filled in. Connect Google Cloud.
- What it reads. The project’s IAM policy (grants to anyone on the internet, owners and editors, personal Gmail accounts, service accounts with owner or editor, project-wide impersonation, data access audit logging), service accounts and their user-managed keys, Cloud Storage buckets and their public grants, VPC firewall rules, Compute Engine instances and Cloud SQL instances.
- Honest about gaps. An API that is off in the project leaves its type empty and is listed on the project. A zone Google Cloud can’t reach leaves instances partial and names it. A refused exchange says which part of the trust is wrong.
- CLI 0.10.0:
tilldev shield posture add gcp --account <project> --audience <provider> [--service-account <email>],trust <id>prints the principal, condition and commands, andaudienceandservice-accountchange them in place.
October 2026 · Posture: AWS accounts
- Connect AWS with no AWS key. Add an AWS connector with the account id, then trust it in three steps: TillDev’s connector issuer as an OpenID Connect provider, a role whose trust policy names that one connector, and a read policy of exactly the calls a sync makes. Each sync assumes the role for fifteen minutes. Shield → Posture shows the steps with your account filled in. Connect AWS.
- What it reads. The account’s root MFA and keys, password policy and S3 Block Public Access; IAM users from the credential report; IAM roles and who their trust lets in; S3 buckets; and in each enabled region, default EBS encryption, security groups, EC2 and RDS instances and CloudTrail trails.
- Honest about gaps. A region the role can’t read leaves those types partial and names the region; list the regions you use and the next sync reads in full. A setting the role can’t read is marked unread, never guessed. A sync that can’t start a session says why.
- CLI 0.10.0:
tilldev shield posture add aws --account <id> [--role] [--regions],trust <id> --out .writes the trust and read policies, androleandregionschange them in place. A federated connector’s first sync is now started by hand, once the account trusts it;sync_idis null until then.
October 2026 · Posture: what your infrastructure looks like
- Connectors that only read. Under Shield → Posture, connect a provider and it reads that account’s settings on a schedule, daily unless you set hourly or off, into an inventory: each resource, the settings that matter for security, and when it appeared, changed and went. Settings only, never secret values. Posture.
- Start with your own workspace. The TillDev connector reads your TillForge repositories and the policy guarding each default branch, TillSecrets service tokens, API keys and TillAuth apps.
- No cloud keys stored. Cloud accounts will connect through federation: TillDev signs a token that lasts five minutes, and your account trusts the issuer and the connector’s own subject. Providers without federation keep a read-only token sealed in TillSecrets, unsealed only for a running sync and never returned. AWS, Google Cloud, Azure, Cloudflare and DigitalOcean open next.
- An inventory you can trust. A resource leaves the inventory only when a sync read its whole type and didn’t find it. A type that couldn’t be read in full keeps what it had, and the sync says so. Removed resources stay visible for 30 days.
- CLI 0.10.0:
tilldev shield posture add | show | sync | schedule | rename | token | syncs | rm | resources.sync --waitexits 1 when the sync fails. API:/api/shield/posture, documented in/openapi.json.
October 2026 · TillCache: atomic queues, dead-letter replay, pattern subscriptions
- Fixed: queue operations on the managed backend weren't atomic. A pull could lose a message if it was interrupted, two consumers could receive the same message, and acking a message whose lease had expired could delete the copy another consumer was working on. Each push, pull, ack and nack is now one atomic step, and every delivery gets its own receipt. Delivery is first in, first out on every backend. Queue semantics.
- Dead letters you can act on.
queue.deadLetters(),replay()andpurgeDead()inspect, requeue or delete messages that ran out of retries. Dead letters are kept for 14 days. A repeateddedupeKeynow returns the first message's id withdeduped: true. Needs@tillstack/cache-*0.4.0. Dead letters. - Replay dead letters from the dashboard. On the Queues page, owners and admins open a queue's dead letters, read each message's body and failure, and replay or purge the ones they pick, or all of them. Each action is written to the audit log. The same is available over the API and as
tilldev cache dead,replayandpurge-dead. Dead letters. - 24 hours of queue history. Each queue on the Queues page now charts its peak depth and the longest wait of its oldest message over the last day, in half-hour steps. The API returns it as
lag_history. Observe. - Pattern subscriptions.
subscribe('orders.*')hears every matching channel on one stream. Pub/sub guide. - Storage cap and default TTL are enforced. Writes that would grow a full namespace answer
507; reads and deletes keep working. A namespace's default TTL now applies to every key written without one. Queue pushes count toward the daily queue-message allowance, and pub/sub deliveries toward the command allowance. KV guide. - Faster commands. Rate limiting and quota now cost one round trip instead of up to four, and a read runs alongside its quota check.
- Queue gauges on every backend. Depth, in-flight, dead-lettered and the age of the oldest waiting message now show for Durable Objects namespaces too, which previously read zero. The usage page lists the slowest command shapes from the last two hours.
- Usage charts cover the whole week. The Usage page charts every hour of the last seven days for commands, queue messages, publishes or stored bytes, in your local time, with a daily trend on each total. Previously the chart could stop short of the full week. Queues with dead letters show a count in the TillCache sidebar. The API returns the hours as
series, andtilldev cache usageprints the week's trend and its busiest hour.
October 2026 · TillSecrets: layered env files
tilldev secrets exectakes more than one--env-file. Layer a shared file of references with a per-pod or per-service one instead of merging them by hand. For a key in more than one file, the later file wins, and the CLI names the override on stderr without printing any value. All references are still resolved in one audited request, and the command doesn't run if any fails. Needs@tillstack/cli0.10.0. Broker guide.
October 2026 · TillPulse: offline events encrypted on every SDK, page-hide delivery fixed
- Fixed:
@tillstack/browsercould lose up to 50 events each time a tab was hidden. The page-hide send couldn't authenticate, and the SDK deleted the events anyway. In 0.4.0 it sends with akeepaliverequest and removes an event only once ingest has accepted it; where that isn't possible, a beacon carries the events and they stay queued until confirmed. - The browser SDK's offline queue is encrypted. Events waiting to be sent are stored with AES-GCM under a key the browser generated and can't export. Stored events that fail their integrity check are discarded, and reported as
storage_tamperwhen threat detection is on. Events older than 24 hours are dropped.TillPulse.clearQueue()wipes the queue and its key. This doesn't protect against script running on your own page. @tillstack/electron0.4.0 encrypts its queue file with AES-256-GCM under a data key the OS keychain protects (Keychain, DPAPI or the Linux secret service), readable only by your user. An edited queue file fails authentication and is discarded. Without a keychain the queue stays in memory unless you setallowPlaintextQueue. It also addsclearQueue().@tillstack/react-native0.4.0 and the Flutter SDK encrypt their offline queues. On Android the queue is sealed with AES-256-GCM under a key wrapped by the Android Keystore (StrongBox when present); on iOS and macOS under a keychain key that never syncs or leaves the device; on Windows (Flutter) with DPAPI. The key never reaches JavaScript or Dart, a tampered queue is discarded, a queue left by an older version is rewritten encrypted, and stored events expire after 7 days. Where there is no key store (Expo Go, Linux) events stay in memory and are never written in the clear. React Native · Flutter.- Fixed: the React Native iOS module didn't compile with current Xcode. It declared its own start-up hook alongside React Native's module registration, and its crash handler used a memory-read call the iOS SDK no longer allows. Both are fixed in 0.4.0, and the same crash-handler fix ships in the Flutter SDK.
- Fixed: an event from an older release marked a resolved issue as regressed. An issue now regresses only when it reappears in a release newer than the one it was resolved in, judged by version number or, for other release names, by when each was deployed. The regression alert fires once.
- Fixed: issue counts could undercount under load, and an offline backlog arriving late moved an issue's last-seen time backwards. Counts are now exact however many events arrive at once, last seen only moves forward, and a device clock set in the future can't push it ahead.
- Events are processed in parallel, one session at a time, so a busy project no longer waits behind a single queue.
October 2026 · TillAuth sessions and second factors
- Fixed: a refreshed TillAuth session could claim MFA it never did, and magic links, social sign-in and enterprise SSO skipped Till Authenticator push. The
mfaclaim now follows the session, and every sign-in path asks for the account's second factor. Concurrent refreshes no longer split a session, IPv6 magic links bind to the /64, and password checks shed load with503 auth_busy. Details in the TillAuth changelog.
October 2026 · TillDrill: latency by region, and load drills
- How fast it answers, from where your users are. A latency run sends five ordinary requests to a target from each region you pick, four of them in Africa, and times connecting, the TLS handshake, the first byte and the whole answer. Six checks judge it against the target's budget: over budget, a slow first byte, one region far slower than the rest, failed requests, and the target down from some or every region. Run it now from Speed and load on a target, or set it hourly or daily. Any proof allows it. Latency.
- Load drills with a hard ceiling. Plan a ramp, steps, a constant rate or a spike up to 500 requests a second for 30 seconds to 10 minutes, GET or HEAD on one path. A plan past a cap is refused, never trimmed. Only the file on the server allows a load drill, and each one asks you to confirm the plan first. Load drills.
- It stops on its own. Every region checks its error rate and 95th percentile every 10 seconds and stops the whole drill when either passes the threshold you set. Stop it any time and it keeps what it measured. A probe that can't reach TillShield for 20 seconds stops by itself. A workspace can start 10 load drills a day, one at a time, and one target once every 15 minutes.
- Same safety as every drill. The proof is checked again, the name is resolved once, a private address refuses the run, and every request goes to the checked address. Requests carry a TillDrill user agent and an
x-tilldrill-runheader so you can find them in your logs. Starting, stopping and the end of every load drill are in the audit log with who started it. - Regions and their addresses. Shield → TillDrill lists which regions can measure now and the addresses their traffic leaves from, so you can let them through your firewall. When no probe host is online in a region, latency in nine of them is measured from TillShield's edge instead. Regions.
- A scheduled latency run that finds checks newly failing at medium or above sends the same
tillshield.drill.checks_failingalert, withrun.profileset tolatency. - CLI 0.10.0:
tilldev shield drill latency | load | stop | regions,targets latencyandruns --profile.loadasks before it starts unless you pass--yes, and Ctrl-C while it waits stops the drill. API:/api/shield/drill/runs/:id/stopand/api/shield/drill/regions, withprofile,regions,budget_msandplanon/api/shield/drill/targets/:id/runs, documented in/openapi.json.
October 2026 · TillDrill: scan your app builds
- 41 checks of the builds you ship. Upload an APK, an IPA, a zipped .app or a Windows or Linux build, or pick a release asset TillForge stored, under Shield → TillDrill → App builds. TillDrill reads the manifest or Info.plist, the network settings, the entitlements and signing, how each executable was built, and every string in the code and bundled files. Each check is tagged with its OWASP MASVS control and says how to fix what it finds. App builds.
- What it finds. Debuggable and test builds, backups left on, plain-text traffic and App Transport Security turned off, user-added certificates trusted, components any app can open, old target SDKs, v1-only signing, executables without PIE, NX, RELRO, stack canaries, ASLR or CFG, macOS apps without the hardened runtime, secret keys shipped in the app, weak ciphers and hashes, and unsafe hostname checks.
- The build is deleted once read. Each scan reads the build once, within fixed limits, and keeps only the report. A key found in the code is kept masked, never in full.
- New since the last build. Each scan marks the failing checks that passed on the last scan of the same app, so a release can fail on what it made worse.
- CLI 0.10.0:
tilldev shield drill apps upload | from-release | releases | show | checks | rm.upload --waitexits 1 on a failing check at medium or above, or at--fail-on;--new-onlycounts only new failures. API:/api/shield/drill/apps, documented in/openapi.json.
October 2026 · Approvals that work with coding agents
- A coding agent now carries on once you approve. The CLI spots Claude Code, Codex, Gemini CLI, Cursor and opencode. When one of them runs a command that needs your approval, the CLI tells the agent in plain words to ask you, opens the approval in your browser and waits up to 90 seconds. Approve in time and the command finishes. If the agent stops waiting first, it runs the same command again after you approve, and that goes through without asking. Approvals docs.
- You see the request without being told. While the console is open, a request from a terminal appears on whatever page you're on, the tab title counts what's waiting, and Approvals in the sidebar shows a badge. The Approvals page updates by itself, and can send a desktop notification while the tab is in the background. Approvals now sit in the TillSecrets sidebar as well as the workspace one.
- Trust a terminal with everyday secrets.
tilldev approvals trustasks to trust one terminal sign-in for 1 hour to 7 days. While trusted, it reveals and uses secrets below tier 7 without asking; restricted and sealed secrets, and every other action, still ask. Each use is in the audit log. Logging out ends it, and a browser session can't be trusted. Trust a terminal. - An agent token for the agent you're working with.
tilldev secrets agents create --save, run in the agent's session, saves a token named after that agent. When that agent runs a command, it acts as the token, which can spend but never reveal, while your own commands keep your sign-in. Agent tokens. - Clearer records. The approval page and the audit log say whether a request came from a browser, a terminal sign-in or an API key, and name the agent the CLI reported, marked as reported rather than proven.
- The approval, sign-in and Approvals pages are laid out for a desktop screen, with what happens next beside the request.
- CLI 0.10.0:
tilldev approvals wait <id>(exit 0 approved, 1 denied or expired, 3 still waiting),tilldev approvals trust [status|end],tilldev secrets agents create --saveandagents forget, andTILLDEV_AGENT_MODE. API:/api/step-up/trustand/api/step-up/signal, documented in/openapi.json.
October 2026 · TillDrill: passive checks
- 32 checks of what any visitor can see. A passive run reads the TLS versions and certificate, the security headers, cookies, whether plain http moves visitors to https, and the DNS records that protect mail and certificates: SPF, DMARC, CAA and DNSSEC. Each check is tagged with its OWASP Top 10 category, and with ASVS requirements where one fits, and says how to fix what it finds. Passive checks.
- Safe by construction. Every run checks the proof again first. It is refused if the hostname resolves to a private address, and it connects only to the addresses it checked. It makes only TLS handshakes, GET requests and DNS lookups, never reads a page body, and keeps cookie names, never their values.
- By hand or on a schedule. Run a target now from Shield → TillDrill or the CLI. Each proven target also repeats on its own, daily unless you set it to weekly or off. Results are grouped by section and show what was seen for each failure. A check that couldn't run says why and never counts as a pass.
- Alerts when it gets worse. A scheduled run that finds checks newly failing at medium or above sends one security alert by email, Slack and signed webhook, as
tillshield.drill.checks_failing. A run that finds a verified target's proof gone sendstillshield.drill.target_lapsed. - TillTell rules can carry a
remediationnote that says how to fix what they find. - CLI 0.10.0:
tilldev shield drill run | runs | runs show | checksandtargets schedule.run --waitexits 1 on a failing check at medium or above, or at the level--fail-onsets, so it can gate a deploy. API:/api/shield/drill/targets/:id/runs,/api/shield/drill/runsand/api/shield/drill/checks, documented in/openapi.json.
October 2026 · TillDrill: test what you own, from the outside
- Targets come first. Shield → TillDrill holds the sites and APIs your workspace may test: a hostname, or a base URL with its scheme, port and path. Private and reserved names, bare addresses and Till's own domains are refused. The drills that run against targets arrive next. TillDrill docs.
- Prove you own it. Publish a TXT record at
_tillshield.plus the hostname, or serve the same value at/.well-known/tillshield-verifyon the target. A domain the workspace already verified for single sign-on, or a TillAuth custom domain, proves it with nothing to publish. - The proof decides the drill. A DNS record proves the name, but a name can point at anyone's server. Only the file proves the server itself, so load drills need it, and active checks on a DNS proof run over https only.
- Checked again before every run. A drill won't start unless a proof it accepts holds at that moment. A proven target whose proof has gone shows as lapsed, and a DNS outage on Till's side changes nothing. Adding, proving, lapsing and removing targets are in the audit log.
- CLI 0.10.0:
tilldev shield drill targets ls | add | show | check | rm. API:/api/shield/drill/targets, documented in/openapi.json.
October 2026 · Respond on the host: end a process, isolate a host
- End a process from TillShield. From a host under Shield → Endpoints, the CLI or a playbook, an owner or admin can end a process. The agent ends it only if the PID still runs the binary you named, so a PID the system has reused is left alone.
- Isolate a host. Isolation blocks all traffic, connections already open included, except loopback, DHCP, the agent's link to TillShield and up to 16 networks you leave open. The host keeps reporting, so you can watch it and release it from TillShield. It can lift by itself after 5 minutes to 30 days, even if the host can't reach TillShield, or hold until released. The agent uses nftables or iptables on Linux, pf on macOS and Windows Filtering Platform on Windows, and puts back rules that were removed.
- Signed, for one host, once. TillShield signs every command for one host. The agent checks the signature, the host and the expiry before it acts, runs each command once and reports what happened. A command the host never takes lapses, and one still waiting can be called back.
- Undoing it on the host is seen.
tell-agent isolation releaselifts an isolation on the host. If a host reports itself open with no release sent, TillShield records it, and the new TillTell rule “Host isolation lifted on the host” reads it. The library now holds 42 rules. - Two new playbooks.
kill-process-and-notifyandisolate-host-and-notifyact on the host that reported the finding. The web-shell and reverse-shell rules suggest the first; the LSASS rule suggests the second. They wait for a person unless the rule has earned unattended runs. Host playbooks. - CLI 0.10.0:
tilldev shield endpoints isolate | release | kill | commands | cancel, and--status isolated. API:/api/shield/endpoints/:id/commands. Respond.
October 2026 · Endpoints: your hosts join the stream
- The TillTell agent for Linux, macOS and Windows. It reports processes started, sign-ins and failed sign-ins,
sudoandsu, new accounts and group members, persistence, SSH keys, kernel modules, listening ports, cleared logs and defences turned off. It runs in user mode on each system's own event sources, with no kernel driver. TillTell rules, TillHunt, incidents and the coverage map read host events like any other source. - Twenty rules for hosts. The library now holds 41 rules. The new ones cover reverse shells, download-and-run, encoded PowerShell, web shells, proxy execution, LSASS reads, new admins and accounts, autostart entries, services, scheduled jobs, SSH keys, kernel modules, preload hijacks, cleared logs, defences turned off, malware detections, SSH brute force, remote admin sign-ins and an agent going silent. Host events are client-reported, so each suggests notifying people rather than acting alone.
- One signed command per host. The installer checks the release's signed checksum list and the binary before installing anything, then enrols the host and starts the service. Running it again upgrades in place.
- Approval by fingerprint. Shield → Endpoints makes enrolment tokens, shown once, that expire and can be limited to a number of hosts. A new host waits until an owner or admin types the fingerprint the host printed, unless its token approves hosts on its own. Revoking a host refuses its events and stops its agent for good.
- Honest about what it can't see. Each collector on each host is live, degraded or off, with the reason. On Windows a missing audit policy, command lines left out of process events, or a disabled log is named with the command that fixes it. A host that stops checking in for 30 minutes is marked silent, and a rule can act on it.
- Secrets stay on the host. Passwords, tokens, credentials in URLs and private keys are scrubbed from command lines and log text before anything is spooled.
- CLI 0.10.0:
tilldev shield endpoints ls | show | approve | revoke | rename | rm | tokens. API:/api/shield/endpoints, documented in/openapi.json.
October 2026 · Google and GitHub sign-in connect only with your consent
- A matching email no longer signs anyone in to your account. Until now, signing in with Google or GitHub using the same email as an existing account without two-factor connected the two and signed in. Now that account's own address gets a one-time link to connect them, and nothing changes unless you click it. Accounts with an authenticator still connect after its code. Docs.
- Profile → Google and GitHub sign-in connects or disconnects either one while you're signed in. Resetting your password or accepting an invitation disconnects them.
October 2026 · Leak checks: every string, and values that aren't secret
- Every string in a TillForge push is now checked against your vault. Until now, a very large push was compared only in part, and the push didn't say so. Now every distinct string is checked, however large the push. If the vault stops answering partway through, anything already found still blocks the push, and the warning says how much was checked.
- Mark public config as not a secret. A public URL, an account ID or a sender address kept in the vault no longer blocks pushes once it's marked Not a secret (Leaks… on its row, or
tilldev secrets update <secret> --on-leak ignore). Marking one needs an approval. Sealed secrets and secrets at tier 7 or higher can't be marked, and a marked secret that is later sealed or made restricted is checked again. Leak docs. - CLI 0.10.0:
tilldev secrets scanchecks every string in every file instead of stopping at a fixed number. On a large scan it waits for the rate limit to reset rather than failing, and says so.
October 2026 · Approvals open on their own page
- An approval link opens just the approval. When a terminal or agent prints a link because an action needs your approval, the link now opens that one request with no dashboard around it. Approving a terminal sign-in at
/deviceworks the same way. Older links still work and forward to the new pages. Approvals docs. - Each page shows which account you're signed in as. If it's the wrong one, “Use another account” signs you out and brings you back to the same link.
- CLI 0.10.0:
tilldev approvals open <id>opens the new link, and works without a workspace set.
October 2026 · TillHunt: ask the stream a question
- Search your security events in the rule grammar. Shield → TillHunt takes
field:valueterms in a search bar, or selections and a condition in YAML for anything richer. The TillTell rule matcher decides every match, so what a hunt finds is exactly what a rule made from it would fire on. TillHunt docs. - Find who stands out. Group matches by up to five fields and sort by most common or rarest, zoom into the histogram, and click any value to add it, exclude it, start a new search for it or group by it. Findings and incidents link straight to a hunt for their actor, address, session or target, a day either side.
- Honest about what it read. A run checks up to 10,000 candidate events, newest first, and spends up to 3 seconds matching. When it stops short, it says how many candidates it checked, how far back it reached, and lets you scan further back from there. Ranges run from an hour to 400 days. Drill events stay out unless you include them.
- Keep the questions, and turn answers into rules. Save up to 200 hunts per workspace, each with a hypothesis and the result of its last run, or start from five starter hunts. “Make it a rule” drafts a TillTell rule with tests made from the newest match and an event the hunt passed over; it opens in the rule editor and starts in shadow.
- Owners and admins only. Every run is written to the audit log with its query, range and counts.
- CLI 0.10.0:
tilldev shield hunt run | check | overview | ls | show | save | update | rm | rule. API:/api/shield/hunts,/run,/validate,/overview,/ruleand/:id, documented in/openapi.json.
October 2026 · TillTell: rules of your own
- Write detection for the attacks only you would recognise. Shield → TillTell → Rules → New rule opens an editor with a working rule to start from, and “copy as new rule” on any library rule gives you one to tune. Rules use the library's YAML format and run on the same stream. Writing TillTell rules.
- Every rule proves itself before it saves. It needs a test that fires and one that stays quiet, and all of them must pass. Check shows each problem where it is in the YAML, the test results, and the rule's cost against the limits. “Try on recent events” replays up to 5,000 of your events from the last hour to the last week and shows what the rule would have fired on, without saving anything.
- One workspace can't slow another. Regexes use RE2 syntax and run in linear time, so lookaround and backreferences are refused. A workspace holds up to 100 rules, each limited to 1,000 comparisons per event and a regex size of 2,000. A rule that still runs too long is paused, and owners and admins are notified. Resume it, or save a new version.
- Your rules earn their stage like the library's. A new rule starts in shadow. Each save is a new version, and a change to what it detects drops an advisory or live rule back to shadow and clears its automation confirmation. The editor won't overwrite a version someone saved after you opened it. Deleting a rule keeps its findings and history. Every change is written to the audit log.
- The rule library page is now Rules, with the library and your workspace's rules side by side. Playbooks list the workspace rules that suggest them, and the coverage map and incidents count your rules too.
- CLI 0.10.0:
tilldev shield tell rules validate | backtest | create | update | rm | resume, reading a file or stdin.validateexits 1 when a rule has problems, so it fits CI. API:/api/shield/tell/rules,/validate,/backtestand/:id/resume, documented in/openapi.json.
October 2026 · Incidents: one case per attack
- Findings that belong together become one incident. An advisory or live finding joins an open incident when it shares an account, a public address, a session or a target with it within 24 hours, or when the incident holds a rule you've linked to the finding's rule. Shield → Incidents lists them; any finding can be escalated into one by hand. Incident docs.
- Triage in one place. Set the status, severity and assignee, and read one timeline of notes, findings, playbook runs and step decisions. “Assigned to me” shows your open cases. Attach or detach findings, and merge up to 20 incidents into one.
- Resolve with a reason. Close an incident as real, a false alarm or a duplicate, and name the ATT&CK techniques it used. A real incident no rule saw lands in the rule backlog, grouped by technique, and the coverage map marks those techniques with how many incidents went unexplained.
- One alert per incident. A finding that joins an incident no longer rings the bell on its own, and drill incidents never ring. Security webhooks now carry the finding's
incident_id. - Members limited to some projects see only those projects' incidents, findings and playbook runs. An incident can only be assigned to a workspace member. Every change a person makes is written to the audit log.
- CLI 0.9.0:
tilldev shield incidents ls | show | open | note | set | resolve | attach | detach | merge | backlog | dismiss | undismiss,tilldev shield tell escalateandtilldev shield tell links. API:/api/shield/incidents/…, documented in/openapi.json.
October 2026 · Playbooks: from a finding to a response
- A live finding now proposes a response. Every live TillTell rule names a playbook: tell the security recipients, make the account prove its second factor, sign it out everywhere, block the address at the edge for a fixed time, or stop an app session from sending data. The run waits under Shield → Playbooks and in the notification bell until an owner or admin decides. Playbook docs.
- Automation is earned, one step at a time. By default every step waits for a person. Turn on “Run low-blast steps on their own” and notifications and second-factor challenges go ahead alone. A rule that has earned unattended runs, with the TillTell switch on and an admin's confirmation, runs every step. A waiting run reminds the recipients once, then expires.
- Built to resist the attacker it responds to. Account actions need evidence a Till service recorded itself. Nobody can turn down a run aimed at their own account. A block refuses private addresses and fails loudly when no edge key would enforce it. A workspace sign-out reaches pages already open within about 30 seconds. Drills simulate every step and touch nobody.
- Security alerts by email, Slack and a signed webhook. Shield → Settings sets the recipients; email falls back to the workspace's owners and admins. The webhook gets its own signing secret, shown once, verified like alert-rule webhooks.
- Inline WAF rules can carry an
expires_attime and lift themselves, and can match a hashed client address withip_hashes. Hashed-address rules need@tillstack/shield-coreor@tillstack/shield-cloudflare0.3.2; older versions skip them. - CLI:
tilldev shield playbooks ls | show | runs | run | approve | reject | start | settings. API:/api/shield/playbooks/…, documented in/openapi.json.
October 2026 · TillTell: every attack has a tell
- TillTell is the detection engine inside TillShield. Every Till product's server-side record now lands on one security stream: sign-ins and second factors, keys and roles, secret reads and exports, pushes and branch protection, backup deletions, and the decisions TillGate makes at the edge. A library of 21 rules reads it, each tied to a MITRE ATT&CK technique and shipped with fixtures that must both fire and stay quiet. TillTell docs.
- Rules earn their way. Every rule starts in shadow: recorded on the TillTell page, never alerting. Owners and admins promote to advisory and live; the system only ever demotes, and only when 20% of a rule's last 20 triaged findings were false positives. Unattended playbooks need 30 clean-enough triaged findings, the workspace switch, and an admin's confirmation.
- Verdicts are for keeps. Judge a finding real, false positive, benign or duplicate; each verdict is appended, never edited, and every stage change is written to the audit log with the numbers behind it. Client-reported events never satisfy a rule that demands server evidence, and drill traffic never counts.
- An ATT&CK coverage map you can trust. Shield → TillTell → Coverage lays the Enterprise and Mobile matrices out by tactic and marks each technique no rule, some sub-techniques, rule, or proven by drill. Draft rules never count. Techniques your connected Till products cannot see are faded, and the ones they can see with no rule running are listed as gaps, each naming the product whose records would close it. How coverage is scored.
- Security event retention is yours to set: 30, 90 or 400 days, under Shield → Settings → TillTell.
- CLI 0.9.0:
tilldev shield tell findings | finding | verdict | rules ls | rules show | rules stage | rules automate | coverage | settings. API:/api/shield/tell/…, documented in/openapi.json.
October 2026 · Two-factor on every sign-in, links that remember, approvals that cover a program
- Security fix: Google, GitHub and company sign-in now ask for your second factor. They used to sign in an account that has an authenticator without asking for its code. Now you enter the code, or a recovery code, before you are in, and a workspace that requires two-factor sends a member without one straight to setting it up. Accepting an invitation on an account with an authenticator sets your password and then asks you to sign in with it and your code.
- Fixed: a link opened while signed out now returns you to it after you sign in. An approval link, an invite, any page: sign in with a password, a passkey, your phone, Google, GitHub or company sign-in, or enrol the two-factor method your workspace requires, and you land where you were headed. Before, some of these paths dropped you on the home page.
- Budget alerts run on their own. Vendor usage is sampled every hour and your budget rules are checked against it, so an alert fires without anyone pressing Sync. A connection that failed once is tried again each hour instead of falling silent until someone noticed, and the platform's own AI-spend connection is no longer polled as if it were a vendor.
- An approval can cover a program with any arguments. When you allow
tilldev secrets execto repeat, choose whether it covers that exact command or the program it starts with, sorunpod.shwith any pod, orbash deploy.shwith any target, needs one approval for the window rather than one per run. The Approvals page andtilldev approvalsmark those. API:programon the resolve call,repeat_scopewhen approving, both on the approval. Repeat. - CLI 0.8.0 is what redeems an approval from a script or an agent: it keeps the claim, so running the same command again after you approve goes ahead, and
TILLDEV_APPROVAL_WAITwaits for you. Older CLIs ask afresh on every run.
September 2026 · TillGate: passes that stay where they were earned
- Passes are bound to the page that solved them. When a site key has a hostname allowlist, TillGate checks that the visitor's browser is really on a listed host, so a copy of your widget on someone else's site can't mint passes for yours. The widget has to run on a page with a real origin: a sandboxed iframe needs
allow-same-origin. TillGate docs. - One attestation, at most five checks. On Fortified sites a device attestation covers up to five checks while it's valid, so one device can't vouch for a fleet of clients. Attestations that would stay valid for more than an hour are refused, including ones that leave out when they were issued.
- WAF challenges bind the pass to the solver's IP.
@tillstack/shield-cloudflare0.3.2 sends the visitor's IP when it exchanges a TillGate token for a pass cookie, so a token solved from another address is refused.
September 2026 · TillArk: base backups that store only what changed
- Incremental and differential base backups. On WAL-G and pgBackRest sources, a policy can have each base backup store what changed since the last full backup (
differential) or since the backup before it (incremental), with a full one at least everyfull_everydays (default 7). Set it on the Policies page, withtilldev ark policies update <id> --incremental incremental --full-every 7d, or in a policy file. Incremental and differential base backups. - Checked before anything builds on it. The agent checks the backup it builds on against its signed manifest (with WAL-G, every backup in its chain) and takes a full one instead when it has changed or is gone. The Backups page and
tilldev ark backups lsshow what each backup builds on, and why one ran full. A restore checks every file it reads, in every backup the chain holds, against the signed manifests. - Chains are kept and quarantined whole. A backup stays while anything kept builds on it, whatever its retention says. A backup built on a quarantined one is quarantined with it; dismissing the alarm releases them together, and restores and clones of a backup held by another's quarantine name that backup.
- API:
incrementalandfull_every_dayson policies;kind,parent_backup_id,kind_noteandquarantined_viaon backups;cleared_dependentsandquarantined_viawhen triaging a canary event. Documented in/openapi.jsonand in the TillArk API. - In CLI 0.8.0:
--incrementaland--full-everyonark policies createandupdate, and a KIND column inark backups ls. Needs this release of ark-agent; older agents take full backups.
September 2026 · An honest status page, and custom domains that watch themselves
- Fixed: the status page could show a component's last reading long after checks stopped. Components are checked every 5 minutes from outside the platform; a reading older than 15 minutes now shows as no data until the next check.
- TillAuth custom domains are checked every 6 hours, and owners and admins are alerted before a certificate lapses or when DNS stops reaching TillAuth. Clients that can only set
Authorizationcan name their app with a publishable key. Details in the TillAuth changelog.
September 2026 · TillArk: runs that come back as of one moment
- Consistent runs. Restoring or verifying a run now brings each store back as of the same moment where its backup allows it, and the run's page,
tilldev ark runs showand the API say whether the run is consistent. When it isn't, they name each store read over time (Redis, ClickHouse, Meilisearch, directories, an unversioned bucket) and say why. One moment. - Versioned buckets. A bucket with S3 versioning on is backed up with every version current from five minutes before the run until its backup began, so a run restores it as of the run's point. An object gone by then comes back from its nearest version within the clock uncertainty, so a restored row never names a missing object as long as your application stores an object before its row and removes the row before the object. The key needs to list and read object versions and read the bucket's versioning setting.
- Snapshots that say when. Logical PostgreSQL dumps, MySQL dumps whose tables are all InnoDB or MyRocks, and whole MongoDB replica sets are recorded as read at one moment, timed on TillArk's clock. Point-in-time databases and versioned buckets recover to that moment on their own clocks. A verification now recovers point-in-time databases to the run's point too.
- Each backup says when it read, and why it failed. The Backups page shows when each backup read its data and, for a failed backup, the reason; before, a failed backup showed only its status.
tilldev ark backups lsprints the reasons under its table, and the API returnserrorandcaptureon each backup. - TillArk reads a run's buckets after its other stores, holding one back for up to 15 minutes while another store's backup waits for an agent. Needs this release of ark-agent: backups from older agents don't record when they were read, so their runs aren't called consistent.
September 2026 · TillArk: failover across more servers, and three durability tiers
- Up to nine servers per source. A self-managed PostgreSQL source with streaming replication can now list two to nine servers. A failover promotes the replica with the least lag after it streams anything another standby received beyond it; the other standbys follow the promoted node onto its new timeline instead of needing a reseed, and one that was down during the failover is pointed at it once it returns. Logical replication stays at two servers. Three or more nodes.
- Quorum commit. With
sync_count, the agent keepssynchronous_standby_nameswaiting for any k of several standbys;asynckeeps a distant node out of the wait. Quorum members show as modequorum. When the old primary is unreachable, a replica that has received as much as enough of the quorum is proven to hold every acknowledged commit. Let TillArk keep it set. - Three durability tiers. The Failover page,
tilldev ark failover statusand the API show whether a synchronous replica holds every acknowledged commit, whether a replica on another provider could take over now, and whether the WAL archive is keeping up. A tier that lapses opens an alarm,offsite.lapsedorarchive.lapsedfor the new two, in your alert rules and the notification bell. Durability tiers. - Agents: set
replication_dsn_envon every node, and give the agent's rolepg_read_all_settingsandALTER SYSTEMonprimary_conninfoon PostgreSQL 13 or later, so standbys can follow. Needs this release of ark-agent. Set up the agent. - API:
durabilityonGET /api/ark/failover,quorumas a replica's mode, and theoffsiteandarchivealarm families with their signals. The TillArk API has the same on/failover/status. Documented in/openapi.json. - In CLI 0.8.0: a Durability tiers table and the
quorummode inark failover status.
September 2026 · TillForge: every backup proven by rebuilding every repository
- Backups through TillArk. Git servers are backed up through TillArk: each repository's history, its Git LFS objects and deleted repositories awaiting purge, sealed under the organization's key before they leave the server, to storage in the server's own region. Before, backups left out LFS objects. Encryption at rest.
- Proven, not assumed. Each backup is restored on the git server it came from, which rebuilds every repository, runs
git fsck, checks every LFS object against its hash and compares each repository's refs and LFS objects with the counts signed when the backup was taken. A check never mints a key. - See it. TillForge → Encryption shows the newest verified backup for each region, when it was checked, and any git server holding your repositories without one. Erasing an organization's repositories makes its backups unreadable, and a backup taken before the erasure no longer counts.
- API:
backuponGET /api/forge/encryption, overall and per region. In CLI 0.8.0: a verified backup line and a BACKUP column inforge encryption. - TillArk: a new source type, TillForge git node (
--type forge), whose backups, verifications and restores run on the node itself. TillForge git nodes.
September 2026 · TillForge: choose the region your repositories are stored in
- Data region. An owner picks the region, from those TillDev runs git servers in, where the organization's repositories are stored: their files, history and LFS objects, and every clone, fetch and push. Names, settings, pull requests, issues, CI logs and release downloads are held centrally. Existing repositories stay where they are. Data region.
- Each region has its own git host, and git is sent on to the right one. A git server gets an organization's repository key only if it holds its repositories or serves its region. Runners can be tied to a region. TillForge changelog.
September 2026 · TillAuth: every app signs with its own key
- New TillAuth apps sign tokens with their own key under their own issuer,
https://auth.tilldev.dev/realms/<app id>, with a key set that holds only that app's keys. Older apps switch under Settings → Token signing or withtilldev auth signing. Switching changes the issuer on the app's tokens;@tillstack/auth-node0.4.0 follows on its own, while pinned verifiers and OIDC clients move to the app's issuer. Rotations publish the new key 15 minutes ahead and keep the old one verifying for 24 hours. TillAuth changelog. - Fixed:
@tillstack/auth-nodeset up with the public id, as documented, refused every token. 0.4.0 accepts the public id or the app id. - Fixed: custom domain setup showed one CNAME target and copied another, and a verified domain couldn't check its certificate. Custom domains also serve the app's key set.
September 2026 · TillArk: MariaDB fixed, Valkey proven
- Fixed: MariaDB backups always failed verification and couldn't be restored. MariaDB's dump tool switches autocommit off around each table's rows and commits after them, and keeps each trigger as it was written. The check that stops planted code from running refused all of it, and the throwaway server refused to create events. MariaDB now passes the same tests as MySQL against MariaDB 13: a verification, a restore run twice over itself with its triggers, routines, views and events, and a dump planted with code refused before any of it runs.
- Security fix: a restore could create a trigger, event, routine or view in another database. A dump that names a database other than the one being restored is now refused. A trigger whose table is written in a different letter case, which the server may treat as the same table, can no longer fire while rows replay.
- Valkey proven. Valkey 9.1 passes the Redis tests with the access rules in the docs: backup, verification, a restore run twice, and keys that expired since the backup skipped. A key that won't restore now says it may be damaged, not only that the server is older.
- Agents: verifying MariaDB needs
mariadb-install-dbbesidemariadbd. Restoring views, routines, triggers or events that belong to another user takesSET USERon MariaDB, asSET_ANY_DEFINERdoes on MySQL.
September 2026 · TillArk: clickhouse-backup for ClickHouse
- clickhouse-backup engine. Self-managed ClickHouse can now be backed up with clickhouse-backup: MergeTree tables travel as copies of their data parts from a snapshot of the server's disks, not row by row, which takes far less of the server on large tables. Tables on object-storage or encrypted disks, tables set up for lightweight
UPDATE, tables whose names need quoting and every other engine travel as rows, as before. ClickHouse table parts. - Proven in a real server. Verification checks the stored backup against the signed manifest, restores the parts into a throwaway ClickHouse server on the agent that only the agent can reach, and runs
CHECK TABLEon every table, then checks every definition and every table's row count. A damaged part fails it. A real restore loads what that server read, staged and checked like any ClickHouse restore, and leaves the destination untouched when a check fails. - Refused up front, with the fix. A ClickHouse user that is readonly or lacks
ALTER FREEZE PARTITION, a table holding lightweight updates that freezing would leave out (fold them in withALTER TABLE … APPLY PATCHES), and a restore destination without a storage policy the tables use are each refused before anything is copied or changed. - Fixed: some ClickHouse tables failed to restore. A restore created each table under the restoring user's own checks, so a table the source server had accepted, such as one with a
LowCardinalitycolumn of a small number type, could fail. MergeTree tables are now defined the way the server loads them itself. A destination missing a storage policy the tables use is now refused before staging, naming the policy. - Fixed: the ransomware canary compared engines with each other. After a source changed engine, a backup was judged against the previous engine's backups, which read different bytes, so the change alone could raise a false alarm or hide a real one. Each engine now keeps its own baseline.
- Agents: install clickhouse-backup 2.5 or newer and the
clickhouseprogram on the database host, addchbackuptoTILLARK_ENGINESand the source toTILLARK_LOCAL_SOURCES;TILLARK_CHBACKUP_BIN_DIRpoints at clickhouse-backup when it isn't onPATH. The engine needs this release of ark-agent. Agent. - API:
chbackupas a ClickHouse source'sengineand in an agent'sengines. The TillArk API has the same on/sources. - In CLI 0.8.0:
--engine chbackuponark sources createandark sources update.
September 2026 · Company sign-in connects an account only with its holder's consent
- Security fix: a workspace's identity provider could sign in to someone else's TillDev account. Company sign-in matched an existing account by the email address the provider sent, and a workspace admin chooses the provider, so a provider that asserted another person's address got a session as that person, confined to that workspace. Now the provider reaches an existing account only after its holder connects it: from Profile → Company sign-in while signed in, or from a link emailed to the account's own address the first time. Connections made the old way to accounts that already existed have been removed; their holders connect again once. Company sign-in.
- New accounts only on verified domains. Company sign-in creates an account only when the provider marks the address verified and the workspace has proven it owns the domain with a TXT record. We said account creation was limited by the allowed-domains list; with the list empty it wasn't limited at all. Add domains under Settings → SSO or with
tilldev sso domains add. - Resetting your password or accepting an invitation disconnects every company sign-in on your account, and accepting an invitation also ends that sign-in's sessions. Changing a provider's issuer disconnects everyone.
- A provider's endpoints must be https and public; private and internal addresses are refused when saved and again at each sign-in. Company sign-in settings take a signed-in owner or admin, not an API key.
- Company sign-in errors now show on the sign-in page instead of as raw error text, and the state it carries between redirects is encrypted.
- In CLI 0.8.0:
tilldev ssoshows, sets up and changes company sign-in, manages verified domains, and lists or disconnects your own connections.
September 2026 · TillArk: pgBackRest, and point-in-time recovery on SFTP
- pgBackRest engine. Self-managed PostgreSQL can now run on pgBackRest as well as WAL-G: physical base backups and a continuous WAL archive, so a restore can land on any moment the archive reaches. pgBackRest also writes to SFTP targets, checking the host key registered with the target; WAL-G still writes only to object storage. Point in time.
- Checked on the way back. pgBackRest backups are encrypted in the agent with AES-256-CBC. Before recovering one, the agent checks the stored backup against the signed manifest, every restored file against its checksum, and every WAL segment against the checksum it was archived under before recovery replays it. Verification then runs the same checks as for WAL-G. Security.
- Changing a source's engine. Queued backups move to the new engine, and one bound for a target the engine can't write to fails and is reported. With none queued, a backup with the new engine starts at once, so its WAL archive has a base. Backups already taken keep their engine, and the old archive still serves restores to moments before the change; the Sources page and
tilldev ark walmark it retired. - Why WAL isn't being archived. A source's row says when no online agent lists it in
TILLARK_LOCAL_SOURCES, or when the agent that does is too old for its engine or doesn't run it.tilldev ark agents lsshows each agent's engines and the databases it hosts. - Fixed: our WAL-G setup left out two grants. A role that isn't a superuser also needs
EXECUTEonpg_backup_startandpg_backup_stop(before PostgreSQL 15,pg_start_backupandpg_stop_backup), and without them every base backup failed. The setup now includes them, and the agent checks before each base backup and, if they are missing, fails it with theGRANTto run. - Agents: install pgBackRest 2.51 or newer on the database host and add
pgbackresttoTILLARK_ENGINES;TILLARK_PGBACKREST_BIN_DIRpoints at it when it isn't onPATH. Streaming WAL with pgBackRest needs this release of ark-agent. Agent. - API:
pgbackrestas a source'sengine;engine_changewithqueued_backups_moved,queued_backups_failedandbackups_queuedfromPATCH /api/ark/sources/{id};engineon WAL streams;enginesandlocal_sourceson agents. The TillArk API has the same on/sourcesand/wal-streams. Documented in/openapi.json. - In CLI 0.8.0:
--engine pgbackrest, what an engine change did to queued backups, an ENGINE column and retired archives inark wal, and each agent's engines inark agents ls.ark sources updateandark wal --sourcealso take a source's name.
September 2026 · TillArk: policies as a file
- Policy files. Keep every protection policy in one YAML file next to your code and review a change like any other.
tilldev ark exportwrites the policies as they stand,tilldev ark planshows what a file would change, andtilldev ark applyapplies it. A setting the file leaves out stays as it is; a new policy takes the defaults. Policy files. - A plan you can review. Each change is listed setting by setting, from the current value to the new one, and a change that weakens protection is flagged: fewer backups or copies, looser placement or credentials, a looser recovery-point objective, or backups or verification stopped. Policies the file leaves out are listed and kept unless you prune them. A problem in the file is shown at its line and column, with the key you probably meant.
- Every change or none. Apply plans the file again and makes every change in one transaction. If a policy the plan acts on has changed since, nothing is applied.
plan -o plan.jsonsaves a reviewed plan thatapply plan.jsonapplies exactly, and--detailed-exitcodetells CI whether there is anything to change. Each change is recorded in the audit log with the settings it changed and the plan it came from. - The Policies page has a Policy file panel: load the current policies or open a file, plan it and apply the plan. Anyone in the workspace can plan; applying needs an owner or admin.
- Editors complete and check the file with its JSON Schema at
https://tilldev.dev/schemas/tillark-policies.v1.json, which exported files point to. - API:
GET /api/ark/policies/export,POST /api/ark/policies/planandPOST /api/ark/policies/apply. The TillArk API has the same under/policies, where anoperatortoken can create policies from a file and changing or removing them needsadmin. A policy'supdated_atis now described as what it is: it also moves when the scheduler records a run. Documented in/openapi.json. - In CLI 0.8.0:
ark export,ark planandark apply. Fixed: a one-letter flag after a single dash, such as-for-u, was read as an argument, sotilldev shield rules apply -f <file>andtilldev forge push -udidn't work as documented.
September 2026 · TillArk: verification at scale
- Staggered starts. Scheduled verifications on the same schedule no longer all restore at once. Each policy starts at its own place within 60 minutes of its slot by default, keeps that place from slot to slot and always starts before the next one. 0 starts on the slot.
- Older backups, proven in turn. Every 4th scheduled verification by default proves the older retained backup proven longest ago, never-proven ones first, instead of the newest. Proving an older backup doesn't move the recovery point.
- Every stored byte, read over time. On restic repositories each scheduled verification also reads one part of the stored data in full, 1 of 30 by default, and checks every blob against its hash, so data only older backups use is read too. A read waits while a backup or prune uses the repository and is left to a later verification after 20 minutes. Damage fails the verification and names the damaged pack files. Verification at scale.
- The Policies page sets all three and shows when each policy next verifies. The Restores page shows which backup each verification proved and the part it read. The Recovery panel on the TillPulse overview shows how many kept backups a verification has proven and how much of each repository's data has been read.
- Reading the repository needs this release of ark-agent. An older agent restores the backup and reads no part, and a later verification by a current agent reads it.
- API:
verify_spread_min,verify_older_every,verify_read_partsandnext_verify_aton policies,samplingon restores, with the read reported as therepository-readcheck, andcoverageon each source inGET /api/ark/status. The TillArk API has the same on/policiesand/restores. Documented in/openapi.json. - In CLI 0.8.0:
--verify-spread,--verify-older-everyand--verify-read-partsonark policies createandupdate;ark restoresshows what each verification proved and why a failed one failed;ark statusshows what is covered.
September 2026 · TillForge: see how each mirror syncs
- A mirror now shows whether it works. The Mirror panel in a repository's settings shows the mirror's host (never its URL), when it last synced, whether that worked and the error if not, its last success, and its recent syncs. Before, a failing mirror showed up only in the audit log. Mirroring.
- The Egress page lists every mirror in the workspace with the same, and flags one whose host is outside the workspace's mirror hosts, so every sync is refused.
- Setting a mirror up again starts its status over, and an archived or disabled repository's mirror shows as paused.
- API: a repository's mirror status, readable by anyone who can read the repository, and every mirror in the workspace for owners and admins. Documented in
/openapi.json. - In CLI 0.8.0:
forge mirror <repo>with no flags shows its status, andforge mirrorslists them all.
September 2026 · TillForge: the merge queue tests what it merges
- Fixed: the queue didn't test the merge result. We said the merge queue runs a branch's required checks on the exact merge result. It only checked each pull request's own head, so two pull requests that each passed could land together broken. Now, on a branch that requires checks, each entry is merged onto the branch's current tip as a test commit and TillForge CI runs on it. The branch moves to that exact commit once every required check passes there, and only if nothing else landed meanwhile; if something did, the test commit is built again on the new tip and tested again. The merge queue.
- A failing check on the test commit takes the entry out of the queue with the check named, and so do checks that haven't all reported within six hours. A pull request that merges as a fast-forward is its own merge result and lands on the checks its head already passed.
- A
merge_queuewebhook event for CI outside TillForge:testinggives thetrial_refto fetch and thetrial_shato report checks on, andfailedgives the reason an entry under test left the queue. Events. - Fixed: CI couldn't build pull requests from forks. The runner cloned the repository's branches, which don't hold a fork's commits, so the checkout failed. It now fetches the commit a job names when the clone doesn't have it. Update tillforge-runner for fork pull requests and merge-queue test commits; an older runner fails those jobs at checkout.
- Fixed: TillForge webhook deliveries and merge-queue steps started as a request finished weren't guaranteed to run to the end. They now always do.
- The queue screen and the pull request page show an entry under test and the commit being tested, and the pull request page lists the checks on it.
- API: a
testingstatus andtrial(commit, ref, start and deadline) on merge-queue entries, andmerge_queueamong webhook events. Documented in/openapi.json. - In CLI 0.8.0:
forge queueshows entries under test and the commit being tested.
September 2026 · TillForge: branch rules hold for every way a branch moves
- Fixed: merges skipped a branch's push rules. Anyone with write access could merge a pull request into a branch restricted to named members, and a branch that requires MFA to push took merges from sessions that hadn't used MFA. A merge now meets the same rules as a push: the person merging must be named, and must have signed in with MFA where the branch asks for it. Every way a branch moves.
- Fixed: linear history let merge commits in. A pull request merged with the merge strategy wrote a merge commit into a branch that requires linear history. That strategy is now refused there; squash or rebase instead.
- Fixed: the merge queue did the same, and merged every entry with a merge commit. An entry now has a strategy, chosen when it joins (squash by default on a linear branch), and is checked as the person who queued it when it joins and again at its turn. Entries queued before this carry no MFA sign-in, so on a branch that requires MFA to push they leave the queue with that reason; queue them again.
- Fixed: agents could start work branches where their person couldn't push. An agent's work branch now needs the person it acts for to be named when the branch pattern is restricted.
- A commit from the dashboard or API to a branch that requires MFA to push now needs an MFA sign-in, as a push does.
- The queue screen shows each entry's strategy and why a re-queue was refused, where it used to fail silently. The pull request page offers only squash and rebase on a linear branch and lists the rules that apply to the merge.
- API:
strategyonPOST /api/forge/repos/{repo}/pulls/{number}/queueand on queue entries; merges, queue joins and dashboard commits answer 403 withrule: restrictorrule: mfa. Documented in/openapi.json. - In CLI 0.8.0:
--strategyonforge pr queue, and a STRATEGY column inforge queue. Fixed:forge pr queuefailed after a successful join, andforge queueshowed no titles.
September 2026 · TillPulse: alert webhooks are signed
- Every rule's own secret. An alert rule with a webhook gets a signing secret of its own when the webhook is added, shown once in the dashboard, the CLI or the API response, or you set your own. Each delivery carries
X-TillPulse-Webhook-Signature: t=<unix>,v1=<hex>, an HMAC-SHA256 oft.raw_body, so a receiver can refuse a forged or replayed delivery, andX-TillPulse-Delivery, which matches the newdelivery_idandrule_idin the body. Your own headers can't replace either. Verify a delivery. - Fixed: we said alert webhooks were signed when they weren't. Rules made before this have no secret; Pulse settings and
tilldev pulse alerts rulesmark their webhooks unsigned, and Add secret ortilldev pulse alerts rules secret <rule-id>gives them one. TillSecrets anomalies and TillArk signals routed through a rule are signed the same way. - Fixed: members who can't manage alerts could read every rule's webhook headers, Slack and Teams URLs and PagerDuty keys. They now see where each alert goes without the credential; the same applies to budget alert rules, whose Budgets page still sent them to every member's browser. A webhook secret is never returned to anyone.
- Budget alerts are signed too. A budget rule with a webhook gets its own secret the same way, and each delivery carries the same two headers; the body has
type: "vendor_quota"and adelivery_id. An older budget rule that kept its secret on the webhook still signs with it, and also sends the olderX-TillPulse-Signature: sha256=<hex>, until you encrypt it in place with Encrypt secret ortilldev pulse budgets rules secret <rule-id> --keep-current(receivers notice nothing) or replace it. Fixed: budget webhooks dropped the headers you set on them; they're sent now. - Fixed: alert and budget webhooks, and budget Slack messages, followed redirects. A redirect now counts as a failed delivery.
- A signing secret you supply must be 16 to 512 characters, here and for TillForge webhooks.
- API:
webhook_signedon alert rules,webhook_secreton create, andPOST /api/alerts/{id}/webhook-secretto replace it; budget rules are now documented too, withPOST /api/vendor-rules/{id}/webhook-secret. Documented in/openapi.json. - In CLI 0.8.0:
pulse alerts rules secret, a WEBHOOK column inpulse alerts rules,--webhook-secretonsecrets anomalies route, andpulse budgets ruleswithenable,disable,deleteandsecret.
September 2026 · TillForge and TillSecrets: webhook deliveries can't be replayed
- TillForge webhook deliveries can't be replayed. Each delivery now carries
X-TillForge-Webhook-Signature: t=<unix>,v1=<hex>, an HMAC-SHA256 of the timestamp and the raw body, the same scheme as TillAuth webhooks. Refuse a timestamp more than five minutes off and a recorded delivery is useless to anyone who captured it. Before, the signature covered the body alone, so a captured delivery verified forever.X-TillForge-Signatureis still sent for existing receivers; move to the new header. Verify. - Every delivery says which one it is. The body carries
delivery_id, the same on every retry and inX-TillForge-Delivery, andattempt, so a receiver can skip one it has handled. - Every new webhook is signed. Leave out the secret and one is made and shown once. A webhook made without one before is marked unsigned; give it a secret from the Webhooks screen or the CLI.
- Fixed: failed deliveries were retried less than intended. A delivery is now tried six times, at once and then after 1 minute, 5 minutes, 25 minutes, 2 hours and 10 hours; the first retry used to wait 5 minutes and the last never happened.
- Dashboard: Webhooks shows signed or unsigned, with Add one and Rotate secret. API:
POST /api/forge/webhooks/:id/secret,signedon a webhook andsecretwhen one is made, in/openapi.json. In CLI 0.8.0:forge webhook secret, a SIGNED column, andaddprints a made secret. - TillSecrets sync pushes to your endpoint are timestamped too. A
dotenvorcustomtarget with a secret now sendsx-tillsecrets-webhook-signature: t=<unix>,v1=<hex>, so a captured push can't be replayed later to roll your values back. Sync targets.
September 2026 · TillForge: mirrors reach only the hosts you name
- Name the hosts your mirrors may reach. An owner or admin can list the only hosts this workspace's mirrors connect to, such as
github.comor*.git.example.com(its subdomains). A mirror to any other host is refused when it's set up and at every sync, including mirrors that already exist, and setting the hosts lists the mirrors now outside them. With none set, mirrors reach any public https host, as before. Audited. Security. - Fixed: a mirror refused at sync time left no trace. A sync refused because its address was no longer public was skipped silently; it's now in the audit log as a failed sync, once an hour while it keeps failing.
- Dashboard: the Egress page (formerly AI egress) sets the mirror hosts. API:
GETandPUT /api/forge/mirror-hosts, andmirror_hostson a refused mirror, in/openapi.json. In CLI 0.8.0:forge mirror-hosts,setandclear.
September 2026 · TillForge: allowlisting a refused secret lets it through
- Allowlisting a refused secret now lets it through. When an owner or admin allowlists a finding the secret scan refused, the same rule, file content and line pass the next time they're pushed, committed in the dashboard or through the API, or written by an agent. Changed content is scanned again. Before, the allowlist was recorded but the next push was still refused, so the only way through was an inline marker. The push that lands is recorded as allowlisted by that admin, with their reason. Secrets.
- An allowlist can be withdrawn before the content lands, and the content is refused again. Audited.
- Breaking: an allowlisted refusal stays
rejected, withallowlisted_byset, until the push that lands records it asallowlisted. An allowlisted finding is already in history and can't be allowlisted again (409). A finding allowlisted before this change stays as a record; if the push is still refused, allowlist the new finding. - Fixed: findings allowlisted with a marker didn't show in the Findings tab. They're listed now, with who let them through and why.
- Dashboard: the Findings tab shows allowlisted refusals, with Withdraw, and what was allowlisted into history. API:
DELETE /api/forge/repos/:repo/findings/:id/allowlist, andcommit_shaon a finding now names the blob the secret is in, in/openapi.json. In CLI 0.8.0:forge allowlist --revoke, andforge findingsshows rejected · allowlisted.
September 2026 · TillForge: mirrors are checked where they connect, and scanned
- A mirror can't be turned inward. The git server now connects a mirror only to public addresses, checked on the address it actually connects to, so a name that later resolves to a private, loopback or cloud-metadata address is refused. Mirrors use https only and never follow a redirect. Before, the address was checked only when the mirror was set up.
- A pull mirror's history is scanned. Each sync checks what it brings for malformed objects and scans it for secrets, including your TillSecrets values, before the branches move. The upstream already has that history, so a secret can't be refused: it shows up as a mirrored finding to rotate, a private SSH key among them is revoked in every workspace, and a TillSecrets value raises a leak. Mark one handled with a reason once it's rotated. Secrets.
- Breaking: a pull mirror sync fails, leaving the branches where they were, when its URL resolves to a non-public address, it redirects, it isn't https, its history has malformed objects, or its secrets can't be scanned and recorded.
- Dashboard: the Findings tab lists mirrored secrets and counts them until they're marked handled. API:
mirroredin a finding'saction, in/openapi.json. In CLI 0.8.0:forge findingsshows mirrored and mirrored, handled, andforge allowlistmarks a mirrored finding handled.
September 2026 · TillForge: leaked SSH keys are refused everywhere
- A private SSH key that lands in a repository is revoked everywhere. When the secret scan flags a private SSH key and it is allowlisted into history, anyone who can read the repository holds it. Every registration of that key is now revoked in every workspace, it can't be added again, and its commit signatures stop counting as Verified. The git server proves it holds the key before anything is revoked; a push the scan refused revokes nothing. The finding names the key. Leaked keys.
- Published keys are refused. Keys whose private half ships with tools, such as Vagrant's insecure keys, can't be registered for SSH or commit signing.
- Breaking: RSA keys under 2048 bits are refused for SSH and commit signing. One already registered shows as refused · too weak, stops working over SSH and its signatures stop counting as Verified. Make a new key with
ssh-keygen -t ed25519. - Breaking: registered Vagrant insecure keys are revoked.
- Fixed: a key registered in two workspaces worked in only one of them, and someone who registered your public key in their workspace could stop it working in yours. Each registration now governs only its own workspace.
- Dashboard: SSH keys and deploy keys show revoked · private key leaked and refused · too weak; signing keys show not trusted; a repository's Findings list private SSH keys in history. API:
revoked_reasonandweaknesson keys,refusedon signing keys,ssh_keyon findings, and 422 for a leaked key, in/openapi.json. In CLI 0.8.0:forge keys lsandforge keys-account lsshow the state,forge findingsshows the key, andforge signing-key lsmarks keys that aren't trusted.
September 2026 · TillForge: big files go to Git LFS
- Big files go to Git LFS. Every repository has a file size limit, 100 MiB unless an admin changes it. A push that adds a file over it is refused with each file's size and the commands that move it to Git LFS; a new file over half the limit gets a warning. Merges (whatever the strategy), browser edits and API commits hold to the same limit. Files already in a repository aren't affected. File size.
- Git LFS is documented. Every repository takes Git LFS with the same token as git over HTTPS; each object can be up to 2 GiB. Git LFS.
- Malformed objects are refused. Every object a push brings is checked before it is stored, so a crafted tree or a submodule name that points outside the repository can't reach the people who clone it. Defects common in old imported histories, such as a malformed date, only warn.
- Breaking: a push that adds a file over 100 MiB is refused, including the first push of an imported history. Move the file to Git LFS, or have an admin raise or turn off the limit for that repository.
- Fixed: pushes over SSH weren't held to the 2 GiB push size cap that pushes over HTTPS were.
- Dashboard: a repository's Settings → File size limit. API:
max_file_mbon repositories, andfile_limitandlarge_fileson a refused merge or commit, in/openapi.json. In CLI 0.8.0:forge repos update --max-file-mb, and a refused merge prints the Git LFS commands.
September 2026 · TillForge: commits name the person who pushed them
- Commit identity is checked at push. The committer of every new commit and the tagger of every new tag must be the person pushing, so no one can push work under a colleague's name. Rebased, cherry-picked and patched commits keep their author. A repository can also require the author to be the pusher, or turn the check off. The first push into an empty repository is exempt so history can be imported, and a refused push lists the commits and how to fix them. Commit identity.
- Commit emails. Your account email always counts. Add another address and enter the code TillForge emails to it; it then counts for pushes and for signed commits. An address another person in the workspace uses can't be added.
- SSH keys belong to someone. Every member can add their own SSH keys. A person's key reaches only the repositories they can, pushes as them, and stops working when they leave the workspace. Owners and admins add machine keys for automation; like deploy keys and deploy tokens, they belong to no person, so their commits can't name one. SSH keys.
- Breaking: commit identity is on for every repository. A push whose new commits name someone else as committer is refused. Add your other addresses as commit emails, or have an admin turn the check off for that repository.
- Breaking: existing workspace-wide SSH keys now belong to the admin who added them, reach only what that admin can, and push as them. If an admin added a key for a teammate, the teammate should add their own; a key for automation should be added again as a machine key. Keys with no known owner become machine keys.
- Dashboard: a repository's Settings → Commit identity, Signing keys → Commit emails, and who each SSH key belongs to. API:
identity_checkon repositories,machine,ownerandmineon SSH keys, and/api/forge/commit-emails, in/openapi.json. In CLI 0.8.0:forge repos update --identity,forge keys-account add --machineandforge commit-email.
September 2026 · TillForge: post-quantum signed commits
- Hybrid signing keys.
tilldev forge signing-key new --git --global --sign-allmakes an ML-DSA-65 + Ed25519 key on your machine, registers it and has git sign every commit and tag with it. Both signatures must verify, so a signature holds while either algorithm does. git works as usual through a small stand-in forssh-keygen; a signature is about 7 KB. Signed commits. - Require them on a branch. A branch rule can accept hybrid signatures only: Hybrid post-quantum in the rule editor, or
--signed-with hybrid. The editor andpolicy lswarn while no hybrid key is registered. - TillForge signs what it writes. Merges, squashes, rebases and browser and agent edits are signed with TillForge's own hybrid key and show Verified · TillForge.
- Pull requests are checked commit by commit. Before a merge, every commit the pull request brings must meet the target branch's signature rule, whatever the strategy. A refused merge lists them, in the dashboard and the CLI.
- Tags show their verdict next to commits: Verified, Unverified or Unsigned, with a PQ mark for hybrid signatures.
- Breaking: Require signed commits now needs a key registered to the commit's author or committer. It used to accept any signature, even one that didn't verify. PGP signatures are refused on these branches, since TillForge can't verify them; register an SSH or hybrid key instead.
- Fixed: merges, browser edits and agent commits skipped the signed-commit rule. They wrote unsigned commits to branches that required signatures, and a pull request's own commits were never checked.
- Fixed: signed commits were refused on branches that required them, because the git server read every signature as missing.
- API:
signature_suiteon branch policies,hybrid_signing_keysin their responses,suite,key_typeandserveron signature verdicts,GET /api/forge/repos/{repo}/tags/signature, andsignature_problemson a refused merge or commit, in/openapi.json. In CLI 0.8.0:forge signing-key newandgit, andforge policy set --signed-with.
September 2026 · TillForge: encryption at rest per organization
- Each organization's repositories are encrypted on disk under a key of its own. Linux filesystem encryption (fscrypt v2): AES-256-XTS for contents and AES-256-CTS for file names. It covers repositories, LFS objects, deleted repositories waiting to be purged and pushes while they are received. Existing repositories are encrypted in place. Encryption at rest.
- The key stays with TillDev. It is sealed with AES-256-GCM under the organization's data key and handed only to the git server, which must present its secret from an allowed address. Every hand-over is in the TillForge audit log as
repo_key.release, with its reason. - Backups are sealed with the same key before they leave the git server.
- Erase every repository. An owner can destroy the key and delete every repository, with its pull requests, issues, settings and LFS objects; backups can no longer be opened. It needs the organization's slug typed out and a new approval,
repos.erase. Forks in other organizations stay. - After the git server's machine restarts it fetches the keys again. Until it can, repositories answer
503, locked, instead of a false not-found; this now includes a dashboard outage that spans such a restart. - Dashboard: TillForge → Encryption. API:
GET /api/forge/encryptionandPOST /api/forge/encryption/erase, in/openapi.json. In CLI 0.8.0:forge encryptionandforge encryption erase --confirm <org-slug>.
September 2026 · TillArk: restore a run's stores together
- Verify or restore a run as a set. Backups queued for the same scheduled slot form a run, and a run now verifies or restores together: from its page (open it from the Backups page),
tilldev ark runsor the API. A verification restores every store in its own sandbox as its backup was taken. A restore needs a second approver, puts each store you pick into a registered source of the same type, and brings PostgreSQL on WAL-G to the moment the other stores began being read. Restore a run's stores together. - References. Declare that a PostgreSQL column names objects in a bucket or directory, such as
users.avatar_urlnaming keys underavatars/. Whenever a run holding both comes back, the agent reads the column from the restored database and reports every value that names a missing object, the rows naming them and up to five examples. Text, numbers, arrays and JSON strings are read; neither side has to fit in memory. A table's partitions and inheriting tables are read too; foreign ones are not, and the result names them. When row-level security would hide rows from the reading role, the check fails and says so. References. - New signals.
run.passed,run.failedandrun.dangling, for alert rules like any other TillArk signal. - Fixed: verifying a PostgreSQL database with foreign-data wrappers, servers or foreign tables always failed, and so did cloning it. The sandbox now leaves them out and names them in the result: their data lives outside the backup.
- Fixed: verifying a PostgreSQL database that uses table inheritance failed its row counts, because a parent was counted with its children's rows. WAL-G verifications and restores no longer read a parent's foreign children through their server.
- Reference checks need this release of ark-agent. An older agent still verifies the stores; the run then fails and says to upgrade it.
- API:
GET /api/ark/runs,GET /api/ark/runs/{epoch},POST /api/ark/runs/{epoch}/verifyand/restore,POST /api/ark/sources/{id}/referencesandDELETE /api/ark/sources/{id}/references/{name}; sources carryreferencesand restoresrun_restore_id; a reference's result carriesleft_outandleft_out_tableswhen it skipped foreign tables. The TillArk API has the same under/runs/{epoch}and/sources/{id}/references. Documented in/openapi.json. - In CLI 0.8.0:
ark runs(show,verify,restore) andark sources refs.
September 2026 · TillArk: an audit log you can check yourself
- Hash-chained. Each entry in a workspace's TillArk audit log now has a number and a SHA-256 hash over the entry before it, set as it is written. Entries already there were chained in the order they were written.
- Signed checkpoints. TillArk signs the chain with its control plane key (Ed25519 and ML-DSA-65) within a minute of a quiet workspace's new entry, and at least hourly while entries keep coming. It checks new entries on every pass and the whole log daily; if the log stops matching, it raises the new critical
audit.tamperedsignal and stops signing. An audit log you can check yourself. - Verify it on your machine.
tilldev ark audit verifychecks every hash, checkpoint signature and change of key, remembers the newest entry it verified, and on later runs checks what is new and that nothing before it changed. It exits 1 when the log doesn't verify. - The TillArk audit page shows how far the log is signed and checked and each entry's number, and pages back past the newest 200. TillArk entries now appear in the workspace audit log.
- API:
GET /api/ark/auditreturns each entry'sseqandhashand the chain's state aschain, and pages withbefore;GET /api/ark/audit/chainandGET /api/ark/audit/checkpointsreturn what a verifier needs. Documented in/openapi.json. - Fixed: the TillArk page called the audit log tamper-evident before anything made it so.
- In CLI 0.8.0:
ark audit verify;ark auditshows entry numbers and the chain's state, and takes--before.
September 2026 · TillSecrets: workload identity on 16 platforms
- New platforms. Bitbucket Pipelines, CircleCI, Buildkite, Semaphore, HCP Terraform and Terraform Enterprise, Spacelift, Azure managed identities (App Service, Functions, Container Apps and VMs), Vercel, Deno Deploy and Modal can now read secrets with the identity they already have, alongside GitHub Actions, GitLab CI, Google Cloud, AWS, Kubernetes and Fly.io. Jenkins and Forgejo work through Other OIDC. Setup for each.
- A token made for the identity wherever the platform allows it. CircleCI and Buildkite tokens are asked for by the CLI and SDK, Bitbucket and HCP Terraform take the identity's audience in their config, and Vercel and Deno Deploy through their own libraries. Spacelift, Semaphore and Modal always use their own audience; the dashboard and docs say what that allows and what to pin.
- Your organization is always pinned. Each platform takes only its own issuer, and the condition naming your repository, organization, project, stack, workspace or principal must be exact. Buildkite, HCP Terraform, Vercel and Deno Deploy identities remember the ids behind the names they pin, as GitHub and GitLab ones do, so a name deleted and re-created is refused.
- GitHub Enterprise issuers are accepted on GitHub identities, and pinned signing keys on HCP Terraform and GitHub ones.
- The dashboard groups platforms into CI runs, clouds and anything else, with a form and setup steps for each.
- Azure Pipelines is not supported: its tokens can only be exchanged with Microsoft Entra. Use a managed identity on a self-hosted agent, or a host key.
- API: new
presetvalues, andaudienceon create and update for Azure identities. In CLI 0.8.0:--bitbucket,--circleci,--buildkite,--semaphore,--terraform,--spacelift,--azurewith--principal,--vercel,--denoand--modal.@tillstack/secrets-node0.4.0 finds each platform's token, and takesworkload.idTokenfor Vercel and Deno Deploy.
September 2026 · Suite ids on every store, and TillAuth key rotation fixed
- Every store names its suite. TillAuth app secrets, TillPulse integration credentials and dashboard authenticator secrets now start with
aead-aes256gcm.v1|too. Older values stay readable. Every ciphertext names its suite. - Fixed: rotating a TillAuth app's data key skipped webhook secrets, so that app's webhook deliveries then failed. Rotation now re-encrypts them along with provider client secrets, authenticator secrets and linked-account tokens.
- Fixed: a TillAuth key rotation that stopped partway could lose secrets. It was not the single transaction the dashboard described. Both keys now stay readable until every value has moved, and running it again finishes the job.
- In CLI 0.8.0:
auth apps rotate-key <app>(owners, up to 3 an hour). A rotation reports what it re-encrypted and is audited asdek.rotated.
September 2026 · TillForge: through a dashboard outage
- Clones and pushes keep working for up to 72 hours if the dashboard can't be reached, on a copy of access and branch protection signed with Ed25519 and ML-DSA-65 and refreshed on every change. When the dashboard is down.
- A push during an outage is checked against branch protection or refused. It used to fall back to guarding only the default branch.
- Ref-log entries, CI, webhooks, deployments and secret findings from a push made during an outage arrive once the dashboard is back, with the time of the push.
- Fixed: Access Centre repository grants were not applied over git. A member limited to some repositories could clone other internal ones with a token.
- Fixed: SSH keys of a suspended workspace kept working over SSH.
September 2026 · TillArk: signals, alarms and recovery on the overview
- Signals. TillArk records a signal for each backup, verification, restore, canary reading and failover step: 38 kinds, each with a severity. Signal kinds.
- Alarms that open and clear. A recovery point older than its objective, no replica that could be promoted, stalled synchronous replication, DNS records pointing away from the primary or an approved agent gone quiet opens an alarm, checked even while no agent reports. It signals when it opens, when it gets worse and when it clears, and never repeats while nothing changes.
- Sent where you'll see them. A TillPulse alert rule with the new
ark_signaltrigger sends them to Slack, Teams, email, PagerDuty or a webhook, by kind, family, source and lowest severity. Signals of one kind for one source make one alert; a destination that fails is retried after 1, 5 and 25 minutes, then 2 hours, and destinations already reached are not sent it twice; on PagerDuty an alarm's clearing resolves its incident. Signals and alerts. - Recovery on the TillPulse overview. For each source: its recovery point against the objective, the last measured restore time, the verification and real restores of the last 30 days, the replica a failover would promote and how far behind it is, and a failover in progress, with open alarms and the last 7 days of failover steps beside them. A stack shows the same for its own sources. It refreshes every minute. Where to see them.
- API:
GET /api/ark/status(with?stack=),GET /api/ark/alarms, andGET /api/ark/signalsfiltered by source, kinds, severity and time and paged withnext_cursor; theark_signaltrigger on/api/alerts. Documented in/openapi.json. - Fixed: the API reference listed
GET /api/ark/auditas returningentries; it returnsaudit, and takeslimit. - In CLI 0.8.0:
ark status,ark alarms,ark signalsandark alerts route.
September 2026 · TillArk: failover while TillArk is unreachable
- Autonomy. In preview. With automatic failover armed, turn on autonomy and the agent that watches the replica can fail the source over on its own once it has not heard from TillArk for 60 seconds. It keeps the same quorum, application observer, confirm window, cap and cooldown, fences first, and promotes a replica only if it was at most 30 s behind when the primary went down. When TillArk is unreachable.
- Under a signed grant. TillArk signs a grant with Ed25519 and ML-DSA-65 naming the agent, the replica it may promote and the observers whose reports count. It lasts 24 hours, is re-signed hourly and is revoked as soon as it could no longer be met. Observers send signed reports straight to that agent over TLS 1.3, checking the certificate it signs in to TillArk with.
- Rechecked. When the agent reaches TillArk again, TillArk records the failover, rechecks the observers' signed reports and flags a failover they don't support on the failover, in the audit trail and in the notification bell. A report that arrives after a later failover acted is kept as history and moves nothing.
- One agent promotes. While an agent may hold a grant, failover steps for the source go only to it. A lost agent's grant can be released with a second approver.
- Says what's missing. The Failover page and
tilldev ark failover autonomysay whether autonomy is in force and, if not, why: an observer that doesn't hold the grant or can't reach the agent, an agent that refused the grant and its reason, or one that stopped sending heartbeats. - API:
autonomyonPUT /api/ark/failover/auto;auto.autonomy, within_forceandgap, onGET /api/ark/failover; triggerautonomousand the recheck asautonomyon failovers; andPOST /api/ark/failover/autonomy/release. The TillArk API has the same, on/failover/auto,/failover/statusand/failover/autonomy/release. Documented in/openapi.json. - In CLI 0.8.0:
ark failover auto --autonomy | --no-autonomyandark failover autonomy [release]. Needs agents from this release, withTILLARK_PEER_LISTENset on the agent that watches the replica.
September 2026 · Workload identity: read secrets without a stored token
- Sign in as what it is. A GitHub Actions or GitLab CI job, a Google Cloud service account, a Kubernetes service account, a Fly.io app, an AWS role or any OIDC issuer can now read secrets with the identity its platform already gives it. Each sign-in gets a service token that lasts an hour by default, or 5 minutes to 12 hours. Nothing long-lived is stored on the workload. Workload identity.
- Servers with no platform identity. A machine identity proves itself with its host key: TillSecrets sends a challenge that only that key can open. This covers DigitalOcean Droplets, other VPS hosts and bare metal, and it is hybrid post-quantum end to end.
- Conditions you choose. Name the repository, branch, environment, service account or any claim, with
*as a wildcard. GitHub and GitLab identities remember the repository's numeric id on first use, so a deleted repository re-created under the same name is refused. - Revocable and watched. Revoking an identity revokes every token it issued. Each refusal is counted on the identity with its reason and recorded in the audit log. Creating an identity, or changing what it trusts, waits for approval.
- Where to find it. Workload identities under TillSecrets in the dashboard,
tilldev secrets identities, andTILLSECRETS_IDENTITYor--identityonpull,exec --envandlease. The Node SDK readsTILLSECRETS_IDENTITYinload()andcreateClient(). - API:
/api/secrets/projects/{id}/identities, plus/api/secrets/workload/identities/{id},/api/secrets/workload/challengeand/api/secrets/workload/exchangefor workloads. Approval actionsidentity.createandidentity.update. Documented in/openapi.json. - In CLI 0.8.0 and
@tillstack/secrets-node0.4.0.
September 2026 · What protects what, and suite ids on everything stored
- A cryptography inventory. One page lists what each product's cryptography protects, how, and whether it is hybrid post-quantum, symmetric, hashed or still classical, with the TLS and SSH key exchange measured on each endpoint. Cryptography.
- A CBOM. The same inventory as a CycloneDX 1.6 cryptography bill of materials at /cbom.json, for tools that read one.
- Suite ids. New ciphertext in TillSecrets, TillForge, TillCache and for AI provider keys starts with
aead-aes256gcm.v1|, like TillArk's already did. Older values have no prefix, use the same AES-256-GCM and stay readable. A suite the reader doesn't know is refused. - Per workspace.
tilldev secrets crypto, or Cryptography under TillSecrets in the dashboard, counts each store by suite, shows the data key's state and how many service tokens are bound to a host key.--tlsreports the key exchange your machine gets. - Rotate the data key in one step.
tilldev secrets crypto rotate-keyor Rotate data key (owners) re-encrypts every store under a new key and labels what was unlabelled. - Also fixed. Rotating the data key now re-encrypts presigned calls and held drops, which it used to skip and leave unreadable, and AI provider keys, which stopped opening after a rotation.
- API:
GET /api/secrets/crypto;POST /api/secrets/rotation/deknow reportspresigned,dropsandaiKeys. Documented in/openapi.json. - In CLI 0.8.0:
secrets crypto [--tls]andsecrets crypto rotate-key.
September 2026 · Encrypted delivery and host-bound tokens
- Encrypted answers.
pull,exec --envandleasein the CLI and the SDKs now get their answer encrypted to a post-quantum key (X-Wing: ML-KEM-768 with X25519) inside TLS, bound to that one request. A proxy that ends TLS, or a recording of the traffic, sees ciphertext. Nothing to set up. Encrypted delivery. - Host-bound tokens.
tilldev secrets host-key initmakes a key on the host;tokens create --host-key @host-key.pub, or Host key in the dashboard, binds a service token to it. That token then answers only encrypted to that key: a copy of it anywhere else gets nothing. - Alerts. A bound token used without its key is refused before anything is decrypted, opens a high
host_keyanomaly, emails every owner and admin, and goes to any TillPulse rule that matches it. The audit log recordstoken.host_key_refused. - Behaviour change. The CLI and SDKs refuse an answer that isn't encrypted. Against an older server, pass
--no-sealorseal: false. - Also fixed. A project-scoped token reading config from the lease service no longer gets sealed secrets, which it was never meant to.
- API:
host_keyonPOST /api/secrets/projects/{id}/tokens,host_key_fpon tokens, thex-tillsecrets-seal-keyandx-tillsecrets-seal-nonceheaders on pull, lease and config, and anomaly kindhost_key. Documented in/openapi.json. - In CLI 0.8.0:
secrets host-key init | show,tokens create --host-key, and--host-keyand--no-sealonpull,execandlease.
September 2026 · TillArk: clients move with the failover
- DNS records follow the primary. In preview, on PostgreSQL you run. With
switchin the agent's failover config, the agent points your Cloudflare DNS records at the promoted node after the old primary is fenced and before the node takes writes, and reads them back first. If the promotion fails, it sets them back. A failback moves them the same way. Moving clients. - Or tell your own system. A webhook gets signed
switch,revertandpromotedevents, with an HMAC-SHA256 signature inX-TillArk-Signature. Answering 4xx toswitchrefuses the move. On Neon, where a DNS record can't move clients between endpoints, and on PostgreSQL you run. The webhook. - Checked before anything is fenced. The agent reads the records before fencing, and reports where they point every minute. A problem that won't pass on its own, such as a revoked token or a missing record, makes every replica unpromotable until it is fixed.
- Drift is flagged. Records that point away from the primary outside a failover show on the Failover page, in
tilldev ark failover statusand in the notification bell. An owner or admin can have the agent point them at the node it finds taking writes; it refuses if both nodes or neither take writes, and the outcome is in the audit trail. - API:
switchonGET /api/ark/failover, andPOST /api/ark/failover/repoint. The TillArk API has the same, on/failover/statusand/failover/repointwith an admin token. - In CLI 0.8.0:
tilldev ark failover repoint, and the client switch inark failover status. Needs an agent from this release.
September 2026 · Post-quantum keys, made in the vault
- Five new key types.
tilldev secrets genand Generate in vault make ML-DSA-65 (FIPS 204) and SLH-DSA (FIPS 205) signing keys, ML-KEM-768 (FIPS 203) and X-Wing (ML-KEM-768 + X25519) encapsulation keys, and a hybrid ML-DSA-65 + Ed25519 signing key. The private key stays in the vault; you get the public key and its fingerprint. Post-quantum keys. - Standard formats. PEM by default, in the forms OpenSSL 3.5 and Node.js read, or raw base64 with
--format raw.--slh-setpicks one of the twelve SLH-DSA parameter sets. - Rotation shows the new public key. Rotating any key pair from the dashboard now shows its new public half, with a button to copy it, including from an open leak.
- Limits. The hybrid follows an IETF draft that isn't final, and OpenSSL can't load it yet. Post-quantum keys can't be used with the SSH agent. This doesn't change how TillSecrets encrypts or delivers your values.
- API:
ml-dsa-65,slh-dsa,ml-kem-768,x-wingandml-dsa-65-ed25519fortype,rawforformat, andslhSetonPOST /api/secrets/environments/{envId}/secrets/generate. Documented in/openapi.json. - In CLI 0.8.0: the new
--typevalues,--format rawand--slh-set.
September 2026 · Leaked values: your secrets, found where they shouldn't be
- Pushes checked by value. In a workspace with TillSecrets, a TillForge push carrying any current or old vault value is refused, whatever the value looks like, and the admins are told. Commits made in the dashboard, through the API or by an agent are checked the same way before anything is written.
tillforge:allow-secretlets a reviewed value through and still tells the admins; agents can't allowlist. Leaked values. - Redacted in TillPulse. A vault value in an error message, breadcrumb or header is replaced with
[REDACTED:vault-secret]before the event is stored. - Check files yourself.
tilldev secrets scan .lists files holding a vault value;--stagedchecks the next commit and--install-hookruns that before every commit. Only candidate strings leave your machine, compared by keyed hash. A value outside your access stays unnamed and is reported to the admins. - A leak is an anomaly. Kind Leak under Secrets → Anomalies: high for a current value, which is emailed to every owner and admin, low for an old one. The secret shows Leaked in its environment, and TillPulse rules take
--kinds leak. - Rotate on leak. A secret the vault generated can be rotated from its recipe with Rotate… or
tilldev secrets rotate, which also revokes the TillDev credentials old values carried. With--on-leak rotateit rotates itself when its current value turns up in a push or a TillPulse event. - Agent allowlists are recorded. When an allow marker let a pattern-scanner finding through in an agent's commit, nothing was recorded. It now shows as an allowlisted finding, and the agent's pull request lists it for the reviewer.
- Limits. Only exact values are recognised, not encoded or partial ones. If the vault can't be reached, a push goes through with a warning and a TillPulse event is stored as it arrived. History already in a repository isn't checked.
- API:
POST /api/secrets/leaks/check,POST /api/secrets/secrets/{id}/rotateandon_leakonPATCH /api/secrets/secrets/{id}; secret lists carryon_leak, and for adminsrotatableandopen_leaks. Documented in/openapi.json. Audited asleak.detectandleak.check. - In CLI 0.8.0:
tilldev secrets scan,secrets rotateandsecrets update --on-leak.
September 2026 · Dynamic secrets for MySQL, Redis, AWS and your own endpoint
- MySQL and MariaDB. Each lease is a user with a random password and your grants, dropped with its open sessions on revoke or expiry. An optional expiry event lets MySQL drop the user itself even if TillSecrets can't reach it. MySQL.
- Redis and Valkey. Each lease is an ACL user with your rules; revoking deletes it and disconnects its clients. Rules that set passwords or switch users on or off are refused. Redis.
- AWS. An STS session on a role, which AWS expires itself and an early revoke denies on the role, or a throwaway IAM user and access key deleted at expiry. Works in the commercial, GovCloud and China partitions. The docs list the least the stored key needs. AWS.
- Your own endpoint. A
custombackend POSTs a signed request to your HTTPS endpoint for each lease and to your revoke URL when it ends, signed like TillAuth webhooks. Custom. - TLS checked by default. MySQL and Redis connections verify the server's certificate against its name, with an optional CA of your own.
- A missed drop is retried. If a revoke or an expiry can't reach the upstream, the lease shows Drop pending and the drop is retried about every five minutes until it goes through. Before, it was recorded and not tried again. Expired leases are now dropped within about a minute. This covers Postgres, API-key webhooks and TillForge tokens too.
- API-key webhooks are HTTPS only. They no longer follow redirects, and their URLs are checked when the backend is registered. An
http://webhook URL, which sent its authorization header unencrypted, is refused; a lease whose revoke webhook washttp://shows Drop pending until you update the backend to anhttps://URL. - Update a backend in place. Rotate its admin password, change grants or TTLs from Update on the backend or
tilldev secrets backends update, sending only what changes. Pointing a backend at a new host, port, TLS setting or URL needs its password or secret again, so a stored credential never goes somewhere new. Updating a backend. - The dashboard has a form for each type.
tilldev secrets backends create --type mysql --config-stdinregisters one from the CLI;tilldev secrets leases --pendinglists leases waiting on a drop andleases revokerevokes any lease as an admin. A lease revoke that isn't confirmed upstream warns. - API: each type's config is checked when you register it;
PATCH /api/secrets/projects/{id}/backends/{backendId}updates one; lease lists carrydrop_failed_at, andPOST /v1/lease/{id}/revokeanswersupstream: dropped | pending. Documented in/openapi.json. - In CLI 0.8.0.
September 2026 · Canary secrets
- A secret nothing should use.
tilldev secrets gen AWS_SECRET_ACCESS_KEY --env prod --type canary --shape aws, or New canary under Secrets → Canaries, stores a decoy that looks real. The first use raises a high anomaly and emails every owner and admin. Canaries. - Three shapes. An AWS key pair backed by a real IAM user that can do nothing, made in an AWS account you choose; use against AWS is picked up within minutes to hours. A Postgres connection string whose host refuses every sign-in and reports the client's address. A Stripe key, which trips inside TillDev only.
- Tripwires inside TillDev. Revealing a canary, spending it through the broker, resolving its reference or signing with it trips it, even for you. Overwriting or rolling one back is refused and trips it. Pulling an environment and sync don't, so you can place canaries next to real keys.
- Hidden. Nothing but the canary list says a secret is a canary, and seeing the list waits for your approval every time (
canary.view). Retiring one and changing canary settings wait for approval too. - Through TillPulse. Alert rules on
secrets_anomalytakekinds, so--kinds canarypages on canary hits alone. - API:
type: "canary"on the generate endpoint;GET /api/secrets/canaries,DELETE /api/secrets/canaries/{id},PUT /api/secrets/canaries/settings. A write or rollback to a canary answers 409. Documented in/openapi.json. Audited ascanary.create,canary.retire,canary.configureandcanary.list. - In CLI 0.8.0:
--type canary,tilldev secrets canaries,canaries rm,canaries settings, and--kindsonanomalies route.
September 2026 · Spend anomalies: an agent spending unlike itself
- Each agent against its own habits. TillSecrets compares every agent's broker spends with its last 14 days. It flags a host or secret it has not used, more spends in an hour than three times its busiest hour, a UTC hour it is never active in, and five or more refusals in 15 minutes. Spend anomalies.
- Within about a minute. Anomalies show under Secrets → Anomalies, with each agent's baseline, and in the notification bell. Medium and high are emailed to the admins behind the spends. The same thing seen again that day is counted, not sent again.
- Through TillPulse. A new alert-rule trigger, TillSecrets: an agent spending unlike itself (
secrets_anomaly), sends them to Slack, Teams, PagerDuty, email or a webhook. You can set the lowest severity, pick agents and set a quiet period.tilldev secrets anomalies route --project <pulse> --slack <url>makes one. - Only a person closes one. Resolving as expected, revoked or investigated waits for your approval (
anomaly.resolve), so an agent on your login can't silence its own alarm. Resolving doesn't revoke anything. - Limits. It is a heuristic that warns and does not block. New agents are judged only on volume and refusals until they have 20 spends over 3 days. Slow drift becomes part of the baseline. Only agent tokens carry an identity the caller can't choose.
- API:
GET /api/secrets/anomalies,GET /api/secrets/anomalies/baselineandPOST /api/secrets/anomalies/{id}/resolve;secrets_anomalyonPOST /api/alerts. Documented in/openapi.json. Audited asanomaly.detectandanomaly.resolve. - In CLI 0.8.0:
tilldev secrets anomalies,baseline,resolveandroute.
September 2026 · Drop links: a secret from outside the workspace
- Ask a vendor for a key.
tilldev secrets request VENDOR_API_KEY --env prod --external, or New drop link under Secrets → Requests, makes a link that someone outside the workspace can use without a TillDev account. Drop links. - Two channels. The link comes with a 12-character code; send them separately. The link works once, lasts at most 72 hours, and locks after five wrong codes, which also emails you. They see the workspace, your name and email, the key and your note, and nothing about the stored value.
- Held until you accept. What they send is encrypted and waits for review. You see when it arrived, from which address and browser, and whether it matches the stored value, without either value being shown. Accept stores it as the next version; reject erases it; after 7 days it is erased anyway.
- Only a signed-in admin can make, accept or reject one; agent tokens and API keys cannot. A link stops working when the person who made it leaves the workspace. Audited as
request.drop,request.drop_refused,request.accept,request.rejectandrequest.discard. - Fixed:
tilldev secrets requests cancelfailed after cancelling, because the response had no request in it. - API:
externalonPOST /api/secrets/environments/{envId}/requests;POST /api/secrets/requests/{id}/acceptand/reject;dropped_valueon a held request. Documented in/openapi.json. - In CLI 0.8.0.
September 2026 · Presigned calls that run by themselves
- At a time.
tilldev secrets presign … --at 2026-10-01T18:00:00Z(or--at +2h) and TillDev runs the call itself then, unless the machine calls it off first withtilldev secrets call cancel. Runs by itself. - Dead-man.
--dead-man 30mruns it unless the machine checks in at least that often withtilldev secrets call checkin. A droplet whose job hangs or dies still gets deleted. - Once, and you hear about it. A timer runs the call at most once, within about a minute of its time, with the same destination rules and approver checks as any run. The result shows on the call in the broker console and
tilldev secrets presigned ls, is audited aspresign.fire, and is emailed to whoever presigned it. A holder's cancel is audited aspresign.cancel. - Check-in and cancel take the same token, address range and machine proof as a run. Once a deadline has passed, the machine can no longer push it back or cancel it; an admin can still revoke the call.
- The Presign form in the broker console has a Runs by itself field, and the approval page shows the timer.
- API:
fire_at,fire_in_minutesanddead_man_minutesonPOST /api/secrets/broker/presigned, andPOST /api/secrets/broker/call/checkinand/cancel, documented in/openapi.json. - In CLI 0.8.0.
September 2026 · Presigned calls bound to the machine that runs them
- Runs from.
tilldev secrets presign … --from 203.0.113.7 --from 10.20.0.0/16limits a presigned call to addresses or ranges, IPv4 or IPv6. Bound to where it runs. - Machine key.
--bind-keytakes an Ed25519 public key; a server's SSH host key works. Every run must then be signed by the private half, so the token alone is refused.tilldev secrets call --key /etc/ssh/ssh_host_ed25519_keysigns;tilldev secrets call keygenmakes a key when there is no host key to use. Each proof works once, within two minutes. - Refused attempts are loud. A run from the wrong place or without a valid proof uses nothing, is counted on the call in the broker console and
tilldev secrets presigned ls, is audited aspresign.refused, and is emailed to whoever presigned the call, at most once an hour per call. - The Presign form in the broker console has Runs from and Machine key fields, and the approval page shows both.
- API:
allow_cidrsandbind_keyonPOST /api/secrets/broker/presigned;POST /api/secrets/broker/calltakes anx-tilldev-proofheader and answers 403 with areasonwhen it refuses. Documented in/openapi.json. - In CLI 0.8.0.
September 2026 · Sealed secrets: nobody reads them, two owners to release
- Seal a secret.
tilldev secrets seal DATABASE_URL --env prod, or Seal on its row in the console. After that nobody can reveal it, owners included, andsecrets exec,mcp runand the bridge refuse it. It is still set, rotated, spent through the broker, pulled by tokens pinned to its environment, synced, and bound to CI on protected branches. Sealed secrets. - Two owners to release it. An owner asks, with a reason, to reveal it once or to unseal it; a different owner approves or denies. Both steps wait for that owner's approval, and the other owners are emailed. An approved reveal works once, for the owner who asked, within an hour, and the secret stays sealed. Requests lapse after 24 hours. New Releases page under Secrets, and
tilldev secrets releases. - Its tier stays restricted. A sealed secret cannot be lowered below restricted, and only an owner can add a broker destination or a CI binding for it.
- Fixed: a deleted secret could still be used by reference through the broker,
secrets execand the SSH agent. It now stops resolving when deleted, and setting the same key again brings it back rather than leaving it hidden. - API:
POST /api/secrets/secrets/{id}/sealand/api/secrets/releases(list, ask, get, approve, deny, cancel), documented in/openapi.json. The broker has a new refusal code,sealed. - In CLI 0.8.0.
September 2026 · Approve from your phone
- Pair Till Authenticator. Under Approvals, choose Pair a phone and scan the code with Till Authenticator. The phone makes its own signing key, which never leaves it; the code works once, for 10 minutes, and pairing needs the same proof as adding a passkey. Approvals.
- Send to my phone. On an approval page, send the request to your phone. The page shows a number; Till Authenticator shows what is asked, the workspace, where it came from and any repeat window, with three numbers. Pick the one on the page and unlock. A wrong number denies the request.
- Signed on the phone. Each decision is signed by the phone's key, including the repeat window it allows, and checked by the vault. Pairing and removing a phone are emailed to you and in the audit log.
- API:
POST /api/step-up/{id}/push,/api/step-up/devicesand the/api/step-up/phoneoperations for the app, documented in/openapi.json.
September 2026 · An SSH agent whose keys stay in the vault
- No private key on disk.
tilldev ssh keygen infra/prod/DEPLOY_KEYmakes a key inside TillSecrets and prints its public half;tilldev ssh importmoves a key you already have, asking for its passphrase once, and--removedeletes the file after checking the vault holds the same key. SSH agent. - An agent for ssh, git and AI sessions.
tilldev ssh agentserves vault keys over a private socket;tilldev ssh config --writepoints ssh at it andtilldev ssh installstarts it at login on macOS and Linux. The vault makes every signature. - Each use is approved, or allowed for a while. A login to a server your SSH client proved, or a git signature, asks for
ssh.sign, which you can allow for 15 minutes up to 7 days for that server and user, or that namespace. A server that wasn't proven, a forwarded agent or unrecognised data asks forssh.sign_once, one signature at a time. The approval page names the server, the user and the key. - Signed commits.
tilldev ssh git <ref> --global --sign-allsets git to sign commits and tags through the agent. - Agent tokens can sign. An agent run with an agent token signs only with keys in its patterns; each signature asks the person who made the token and counts against its daily budget. An agent token can now also poll the approval it asked for with its
x-tilldev-approvalheader. - Repeat windows in minutes. Approvals now offer the windows each action allows; the API takes
remember_minutes, andremember_daysstill works. - API:
POST /api/secrets/ssh/keysandPOST /api/secrets/ssh/sign, documented in/openapi.json. - In CLI 0.8.0.
September 2026 · MCP servers get their keys from the vault
- No API keys in your AI client's config.
tilldev mcp add runpod --env RUNPOD_API_KEY=secretref://ai/dev/RUNPOD_API_KEY -- npx -y @runpod/mcp-serverregisters the server with its command wrapped bytilldev mcp run. The config names the secret by reference; the value is fetched when the server starts and passed to it alone. Works with Claude Code, Claude Desktop, Cursor, VS Code and Windsurf, and with any client through--configor--print. MCP servers. - Find keys already sitting in configs.
tilldev mcp lslists every server in every client, which get keys from the vault, and which keep them in plain text (by name; values are never printed).tilldev mcp import <name> --to <project>/<env>moves them into the vault and rewrites the entry. - Approved once, quiet after. Each start is a request to put those secrets into that exact command, so the first one asks for your approval in the browser. Allow it to repeat for up to 30 days and later starts don't ask. The approval page says which server asked.
- Share it with your team. With
--scope projectthe entry goes in the project's shared file with no values and no paths from your machine, so it can be committed. Each person resolves the references with their own login. - Fixed: running a command again while its approval was still waiting opened a second request, so approving the first link did nothing. It now points at the request already waiting.
- In CLI 0.8.0.
September 2026 · TillSecrets: approvals for what an agent shouldn't do alone
- Breaking: sensitive actions wait for your passkey or authenticator code. Revealing a secret, running a command with secrets (
secrets exec --env-file), allowing a destination host, consenting to a grant, presigning a call, minting a service or agent token, adding or resuming a sync target, and lowering a tier below restricted now answer428 STEP_UP_REQUIREDuntil you approve them. On for every workspace; an owner or admin can turn it off, which needs an approval too. An AI agent using your login can ask but cannot approve. Approvals. - Breaking: API keys (
tp_) get 403 on those actions. A key cannot approve. Service tokens (ts_), agent tokens and broker spends through a grant are unchanged. - Approve from the dashboard or a link. A request made in the console opens an approval panel in place and carries on when you approve. A request from the CLI or the API carries a link to
/<workspace>/approve/<id>showing what asked, from which IP, and the exact action. Deny it and nothing happens. - In the CLI. A command that needs an approval prints the link, opens it and waits. Without a terminal it exits with code 3; approve, then run the same command again.
TILLDEV_APPROVAL_WAITmakes it wait anyway. New:tilldev approvals,open,deny,policyandforget. - Let one command repeat. When approving
secret.resolveyou can allow that exact command for 1, 7 or 30 days, for a dev server or an MCP server you start often. Approvals → Allowed to repeat lists them, with a Stop button. - Ways to approve. Approvals in the sidebar: add passkeys, or confirm the authenticator you sign in with. Changing them needs proof the session doesn't carry (your password, an emailed link, a passkey or a confirmed code), and each change is emailed to you. Turning sign-in 2FA off and on, or an admin resetting it, clears the confirmation.
- API:
/api/step-up(list, get, approve, deny, factors, policy), thex-tilldev-approvalheader, andSTEP_UP_REQUIREDin the error codes. Documented under the Approvals tag in/openapi.json, which now also coversPOST /api/secrets/broker/destinations. - In CLI 0.8.0.
September 2026 · TillArk: synchronous replication
- See whether a failover would lose commits. In preview, on PostgreSQL you run. The agent reports what the primary's commits wait for (
synchronous_standby_names, and the weakestsynchronous_commityour application's roles commit with), whether the replica is synchronous and, if it isn't, why, and commits stuck waiting for a standby. Once a commit has waited 5 seconds the primary is reported down and the notification bell says its writes are stalled. On the Failover page, intilldev ark failover status, and assyncon each replica in the API. Synchronous replication. - Let TillArk keep it set. With
"synchronous": "required"or"preferred"in the agent's failover config, the agent names the replica insynchronous_standby_namesonce it streams.requiredkeeps commits waiting while the replica is away;preferredstops them waiting after 10 seconds and starts again once it streams. Each change is in the audit trail. - A promoted node no longer waits for a standby that isn't there. A standby copied from a primary with
synchronous_standby_namesset kept it, so once promoted every commit on it waited. The agent now clears it on the node it promotes, in a failover or a failback, unless a standby already streams from it, and says so in the step's notes. - New grant: where
synchronous_standby_namesis set, orsynchronousis configured, the agent's role needsGRANT ALTER SYSTEM ON PARAMETER synchronous_standby_names. Without it the replica is reported not promotable and a failover refuses before fencing. - Fixed: fencing a primary whose commits were waiting for a stopped standby waited with them, since the agent's own commits did too. The agent's sessions now commit with
synchronous_commit = local. - Fixed: the audit list showed no detail for replica events. It now shows the event, the node and what happened.
September 2026 · CLI: sign in from a browser, and stay signed in
- No password in the terminal.
tilldev loginprints a link and a code. Open it in a browser where you are signed in, check the code, the computer name and the IP, and approve. An AI agent can start the sign-in and you approve it, the waytilldev forge loginalready worked.tilldev login --emailkeeps the password sign-in. The page attilldev.dev/devicetakes codes from both. API:POST /api/auth/device/code,/token,/approve. CLI account. - Fixed: parallel commands signed you out. When the hourly token expired, two commands renewing at once looked like a stolen refresh token, and every session you had was revoked. The CLI now renews once for all commands on the machine, and the server accepts a just-rotated refresh token for 30 seconds. A replay after that still revokes every session.
- Fixed: some commands (
secrets presign, uploads,ask) did not renew an expired session and failed with 401. - Fixed: a command could read the config file while another was writing it and act as if you were signed out.
- Signing in again keeps the
tilldev forge logintoken. - Fixed: a command that asked for a hidden value, such as
secrets setwithout a value, printed its result and then waited until you pressed Ctrl+C. It now exits. - Fixed: characters typed or pasted the instant a hidden prompt appeared could be echoed in clear. The terminal stops echoing before the prompt is shown.
September 2026 · TillSecrets: agent tokens, and revoking the token you deleted
- Agent tokens.
tilldev secrets agents create deploy-bot --refs 'infra/prod/DO_*' --budget 50mints ata_token for an AI agent. It can spend secrets through the broker, ask a person for a value and list metadata, only inside its ref patterns and under a daily budget. It can never reveal, pull, grant consent, allow a host or presign, and it acts with its creator's current role. Manage them under Secrets → Agents, withtilldev secrets agents ls | revoke | whoami, or at/api/secrets/agents. New refusals:out_of_scope,budget_exhausted. Agent tokens. - Spend from the CLI.
tilldev secrets spend GET https://api.digitalocean.com/v2/account --bearer secretref://infra/prod/DO_TOKENmakes one brokered request and prints the scrubbed response. - Delete by key.
tilldev secrets rm DO_TOKEN --env prodworks likeset. An id still works. - Deleting a TillDev token revokes it too, if you say so. When a secret holds a token TillDev issued (
tfp_,tfd_,ts_,ta_,tc_,tp_), deleting it asks whether to revoke that token where it was issued;--revoke-linkeddoes it without asking. Rotating it (set,gen, or fulfilling a request) offers to revoke the token the old value held;--revoke-previousdoes it without asking. The console asks in both places. Nothing is revoked unless you choose to, and each revocation is in the audit log of the product that issued the token and in the vault's.tilldev secrets linked <secret>lists them. Revoke on delete. - Fixed: an empty
TILLDEV_AGENT_TOKENin the environment replaced your login in the CLI andcreateBroker(), so every call went out unauthenticated. - In CLI 0.8.0 and
@tillstack/secrets-node0.4.0.
September 2026 · TillArk: fail back, or finish
- Fail back once the old primary has caught up. In preview, on PostgreSQL you run. After the old primary is reseeded and replicates from the new one, an owner or admin and a second approver authorize the failback on the Failover page, with
tilldev ark failover failback, or withPOST /api/ark/failover/failback. The agent checks the old primary applies a fresh write within a second, fences the current primary, waits until the old primary has every write it committed, and switches. With logical replication the demoted node subscribes back without a copy; with streaming replication it is reseeded from the promoted one under the failback's approval. If a step fails before the switch, the current primary takes writes again. Failback. - Or keep the new primary.
tilldev ark failover finish, the Failover page orPOST /api/ark/failover/finishends a failover without failing back, so a new one can be requested and automatic failover resumes. Needs an owner or admin; audited. Finish instead. - Breaking:
tilldev ark failover failbackno longer takes--lag, and the API no longer takesreplica_lag_sec: the agent measures how far behind the old primary is. - Fixed: after a failover, the replica list kept the old roles until the next agent report, so a reseed of the old primary right away was refused as a reseed of the primary. Roles now move when the agent reports the promotion or the failback.
- Fixed: finishing a failover dropped the
--discard-writesrequirement for an old primary that may hold writes the new primary never received. It now holds until a reseed rebuilds that node, and applies only to that node. - Fixed: the notification feed called every finished failover “failed back”.
September 2026 · TillSecrets: give a workflow a secret it never holds
- Ask a person for a value.
tilldev secrets request KEY --env prodprints a link and a one-time code. The person opens the link, sees who will be able to read the value, enters the code and pastes the value into the vault. The command prints asecretref://handle, never the value. Pending requests are under Secrets → Requests; the API isPOST /api/secrets/environments/{envId}/requests. Secret requests. - Presigned calls. Approve one exact HTTP request now, carrying
secretref://handles, and let a machine run it later with atsc_token. A droplet can delete itself at the end of a job without holding the DigitalOcean token that could delete every droplet. Uses and expiry are bounded, the approver's access is checked again when the call runs, and a call can be revoked.tilldev secrets presign,tilldev secrets call,POST /api/secrets/broker/call. Presigned calls. - Method and path rules. A secret's broker destination can be limited to certain HTTP methods and path prefixes:
tilldev secrets broker allow <secret> <host> --methods DELETE --path /v2/droplets. The broker checks them again after substituting the value. New refusals:method_blocked,path_blocked. - A tier for one secret. A secret can have its own sensitivity tier; the one that applies is the higher of the secret's and its environment's. Set it with
secrets set --sensitive,secrets update --sensitivity, or the tier control next to each secret in the console. Sensitivity tiers. - Breaking: restricted keys are withheld from project-wide tokens. A token not pinned to the environment gets every other key, and the names of tier 7+ keys in a new
withheldfield.tilldev secrets pull,secrets exec --envandload()in@tillstack/secrets-nodestop rather than start without them; pass--allow-partialorallowPartialto continue. In TillForge CI, a restricted key reaches protected branches only, and binding such an environment to a repo needs the owner. - TillForge tokens straight into the vault.
tilldev secrets gen FORGE_TOKEN --type forge-token --repo api --scope writemints atfp_token that never reaches your machine. Aforge_tokendynamic backend mints one per lease, which is revoked when the lease ends. forge_token backend. - Help for every command.
--helpafter any command (tilldev secrets presign --help) prints only that command's usage. In CLI 0.8.0. - Fixed: the lease service did not apply a token's key pinning (
--keys), and/v1/configserved a restricted environment to a token not pinned to it.
September 2026 · TillForge: clone URLs and empty repos
- Clone URLs where you need them.
tilldev forge repos createandrepos getprint the HTTPS and SSH clone URLs; the API returns them asclone_urlandssh_url. - A new repo is empty, not missing. Before its first push a repo clones as an empty repository over HTTPS and SSH, where it used to answer “not found”.
tilldev forge refssays it is empty. Empty repos. - Tokens for scripts.
tilldev forge tokens create --quietprints only thetfp_token, for piping to where it is needed.
September 2026 · TillArk: reseed a replica or an old primary
- Rebuild a node from the primary. In preview, on PostgreSQL you run. A reseed replaces everything on a replica, or on the old primary after a failover, with a copy of the current primary. With logical replication the agent empties the node's copies of the published tables and subscribes it again; with streaming replication it runs your
reseed_commandand checks the node then streams from the primary. It needs an owner or admin and a second approver, like a promotion. Start it from the Failover page, withtilldev ark failover reseed, or withPOST /api/ark/failover/reseed. Reseed. - Writes are never deleted silently. An old primary replaced by a replica that wasn't proven caught up may hold writes the new primary never received. Reseeding it needs
--discard-writes(or the checkbox on the Failover page), after you have copied them out. - A partly copied node is never promoted. A failover never fences for or promotes a node while its reseed runs, a reseed never starts during a failover, and a failover that starts first cancels a reseed that hasn't. If the agent stops mid-copy, the reseed fails and says the node may be half-copied.
- Which nodes can be reseeded. The Failover page,
tilldev ark failover statusand the API (reseedon each replica,reseedson the status) show each node as ready or unconfigured, and every reseed with what the agent did. Reseeds are in the audit log.
September 2026 · TillArk: failover for PostgreSQL you run
- Fail over a PostgreSQL pair you run. In preview. Describe the two servers under
postgresin the agent's failover config, kept in step by streaming or logical replication, and the agent works out which one is the primary from the servers themselves, fences it, and promotes the other. Manual and automatic failover both work, with the same four-eyes approval and lag bound as on Neon. Self-managed PostgreSQL. - Fencing you can check. Your application's roles can't log in, new transactions are read-only, and client sessions are ended. A primary the agent can't reach is stopped by a command you give it (
fence_command). If a fenced primary comes back taking writes, the agent fences it again and the audit log shows it. - Nothing committed left behind. While the fenced primary can be reached, the replica applies everything it committed before it is promoted. With logical replication, each sequence moves past the highest value used, and a table the publication has but the subscription doesn't blocks the failover until the subscription is refreshed.
- A guard on replication slots. The Failover page shows how much WAL each replica's slot holds on the primary. With
max_slot_wal_bytesset, the agent drops a slot that holds more, so a stuck replica can't fill the primary's disk, and records the drop in the audit log. - What each step did. The Failover page,
tilldev ark failover statusand the API (noteson a failover,detailandslot_retained_byteson each replica) show what each step did and why a replica can't be promoted. The CLI also shows each replica's node and replication mode. - Fixed: a failover with no replica that could be promoted fenced the old primary before failing, leaving no primary taking writes. It now stops before anything is fenced, on Neon too.
- Fixed: every replica an agent reported was shown as using logical replication, whatever it used.
September 2026 · TillArk: each agent bound to its own certificate
- Every agent has its own client certificate. On first start the agent creates a certificate and key in its data directory (
client-cert.pem,client-key.pem), apart from its signing and sealing keys, and presents it on every connection. TillArk binds the agent to the first certificate it sees and refuses the agent's token with any other certificate, or none, so a stolen token alone can't act as the agent. TillArk → Agents shows each agent's certificate;ark-agent client-certprints it on the host. Agents. - Reset after rebuilding a host. A rebuilt host presents a new certificate. Reset the old one under TillArk → Agents, with
tilldev ark agents reset-cert <id>orDELETE /api/ark/agents/{id}/cert, and the agent's next call binds the new one, without a restart. Resetting needs an owner or admin and is audited. - Key rotations reach idle agents. An agent follows an endorsed rotation of TillArk's key by its next heartbeat, not only its next job, and reports the key it will trust when it next starts. The Agents page and
tilldev ark cp-keylist any agent that would restart on another key, such as one pinned with an outdatedTILLARK_CP_KEY; the API gives it ascp_keyon each agent. TILLARK_CA_FILEnow also covers the agent's connection to TillArk, for a network that inspects TLS with its own CA.- Fixed: an agent given a client certificate with
TILLARK_CLIENT_CERT_PATHignoredHTTPS_PROXYand the usual connection timeouts on its connection to TillArk.
September 2026 · TillArk: agents take only signed work
- Every job is signed by TillArk. The control plane signs each job, WAL archiving lease and clone teardown it sends an agent, with Ed25519 and ML-DSA-65 over the reply and a nonce the agent chose, and the agent acts only when both signatures verify against the key it trusts. A job that fails the check is refused and logged. Work only TillArk signed.
- Pin the key. An agent records the key on first contact in
cp-key.pinin its data directory. To pin it before then, setTILLARK_CP_KEYto the fingerprint shown under TillArk → Agents, fromtilldev ark cp-keyorGET /api/ark/cp-key; the Agents page puts it in the run command. When TillArk rotates its key, the old key endorses the new one and agents follow. A key change without that endorsement stops the agent at start, with exit code 2. - An agent now refuses a control plane that signs nothing, unless
TILLARK_ALLOW_INSECURE_LOCALis set for local testing.
September 2026 · TillArk: automatic failover
- Fail over when observers agree the primary is down. In preview, on Neon. Agents with
TILLARK_OBSERVEprobe a source's primary every few seconds, and TillArk opens a failover only when a quorum of them (2 to 9) have seen it down for the whole confirm window, none running where your application does sees it healthy, and, unless you turn it off, one there sees it down. A cap per window and a cooldown stop it flapping, and a failover no agent has started fencing is stood down if the primary comes back. Arm it on the Failover page, withtilldev ark failover auto --source <id> --arm, or withPUT /api/ark/failover/auto. Automatic failover. - Four-eyes to arm, never to stop. Arming, re-arming after a failed failover and loosening any setting need a second owner or admin and a change reference; disarming and tightening don't. Each change is in the audit log.
- Lag judged at the moment of the outage. During an outage the observers agree on, a replica is judged by how far behind it was when the primary went down, not by the lag now, which only grows while nothing is written. This applies to manual promotes during an outage too. How far behind, in an outage.
- One agent per step. Fencing and promoting are each held by one agent for up to five minutes, and only that agent's report counts. The Failover page and
tilldev ark failover statusshow which agent holds the step and since when the primary has been down. Before, every agent with a replica of the source was sent the step. - Fixed: a failover promote or failback made with a
tark_admin token accepted any approver id other than the requester's own subject, including the requester's own token id and ids that match no token. The approver must now be an active admin or approver token in your org with a different subject.
September 2026 · TillArk: buckets as sources
- Back up an S3-compatible bucket. A files source now takes
s3://KEY:SECRET@bucket/prefix, with?region=and, outside AWS,&endpoint=https://host. The agent streams every object under the prefix into the backup with its content type and metadata, checking each against the MD5 its bucket reported. A verification reads every object back and checks the count against the signed manifest; a real restore writes into another bucket prefix, each write checked, or into a directory underTILLARK_FILE_ROOTS. Only current object versions are kept, and objects encrypted with customer-provided keys (SSE-C) can't be read. Limits. - Buckets on your own network. A bucket whose endpoint is a private address, or a name outside public DNS, gets its backups and real restores sent only to agents that list it in
TILLARK_PRIVATE_TARGETS, as private targets already do. TillArk → Sources names the agents that can take them. Mark a public-looking name private with--privateontilldev ark sources createorupdate, in the dashboard, or withmarked_privatein the API. Storage on your network. - Fixed: clone builds counted as verified restores. Building a masked clone restores a backup, and those builds appeared in the restores list and the overview's verification counts.
GET /restores,tilldev ark restoresand the dashboard now list only real restores and verifications; clones are under Clones.
September 2026 · TillArk: masked clones, and out of preview
- Masked clones, built on your own host. Pick a logical backup of a PostgreSQL source and an agent builds a clone of it on its host: it restores the backup into a private sandbox, masks personal data column by column as it copies rows into a new PostgreSQL server, checks that no sampled original survived, and serves the clone over TLS until it expires. The rows never pass through TillArk. Set
TILLARK_CLONE_LISTENon an agent whose host runs PostgreSQL to host clones; TillArk → Agents shows which do. Masked clones. - Connect to a clone. Connect on a ready clone's card,
tilldev ark clone connect <id>orGET /api/ark/clones/{id}/connectiongives its URL and server certificate; the URL usessslmode=verify-full, so it connects only to that clone. Every connect is audited asclone.connect, and credentials are not handed out if the audit entry can't be written. An unmasked clone's credentials need admin scope. - A clone's card and
tilldev ark clone showlist every masked column and what was done to it, the rows and tables it holds, and anything it had to leave out, such as an extension the host lacks. - Creating a clone now answers 409 with what to fix when no agent can build it, when the backup isn't a PostgreSQL logical backup, or when no approved agent hosts clones, instead of a clone that never became ready.
- Fixed: a long error could leave a job stuck. An agent report whose error or warning text ran past its limit was refused, so the job stayed restoring. Long text is now shortened and the report accepted.
tilldev ark clone lsshows the time a clone has left; it showed 0s before.- Out of preview. Backups, restores, restore-verification, the ransomware canary and masked clones are ready for production data. Failover stays in preview and runs on Neon.
September 2026 · TillArk: every database, keys you hold, copies that can't be deleted
- Seven source types, each proven by a real restore. PostgreSQL, MySQL and MariaDB, MongoDB, ClickHouse, Meilisearch, Redis and Valkey, and files. A verification restores the backup into a throwaway server of its own and runs the checks for its type (row counts, schema hashes, checksums, document or key counts), and TillArk refuses a pass reported without them. Each agent reports which types its host can back up, verify and restore, and gets only those jobs. Restore-verification.
- Customer keys. Put a source under a key that exists only on your agent hosts, and TillArk can't read its backups: the agent derives each repository's password from the key, and TillArk stores only its fingerprint. Create one with
ark-agent byok-keygen, then set it on the source in the dashboard, withtilldev ark sources update <id> --byok <fingerprint>, or asbyok_fingerprintin the API. Jobs go only to agents holding the key, and TillArk refuses a key no approved agent online holds. SetTILLARK_BYOK_ONLY=1on a host that must never run a job under a key TillArk holds. Keys TillArk never holds. - Breaking:
byokon a policy is refused. It was accepted before but never took effect;truenow answers 400 with where the key is set instead, and the CLI's policy--byokflag is gone. - Storage on your own network. A target can be a MinIO, S3-compatible store or SFTP server at a private address or a name outside public DNS, and its backups, verifications, restores and deletions go only to agents whose host lists it in
TILLARK_PRIVATE_TARGETS. Each agent reports its list; TillArk → Targets names the agents each private target's jobs go to, or says none can. Mark a public-looking name that resolves privately with--private, or in the dashboard. Loopback, link-local and cloud metadata addresses are refused as targets. Storage on your network. - Breaking: the agent never connects to link-local or cloud metadata addresses, even inside a network listed in
TILLARK_PRIVATE_TARGETS. Storage there needs another address. - Object lock, checked.
tilldev ark targets create --lock-days <n>(S3, B2, Wasabi, MinIO) makes the agent read the bucket's lock configuration before every backup and WAL upload, and refuse to write if new objects aren't locked for that long. The target shows the mode and retention it found. Copies a stolen key can't delete. - Breaking: a target marked immutable is now one whose lock is confirmed. The flag used to be a label nothing checked. Targets marked immutable without a retention, or on a provider without object lock, are now shown as mutable; set
--lock-daysto protect them. - Credential domains. Name the account that holds each target's keys (
--credential-domain), and a policy with--separate-credentialskeeps its copies under different ones, so one leaked storage key reaches one copy at most. When the targets can hold fewer copies than a policy asks for, the policy says so asplacement_problem. Anti-affinity. - Recovery point, measured. Each source shows the newest moment a restore could bring back now, from signed, restorable backups only. Policies take an RPO objective (
--rpo), with a default from the schedule; a breach turns the source red and lands in your notifications. Recovery point. - Backups of several sources queued together share a run:
tilldev ark backups ls --epoch <n>lists the set. - Safer failover. A replica is promoted only with a lag measured in the last five minutes and at most 30 seconds, and the agent measures it again just before promoting. A lag never measured counts as not caught up. When the primary is gone and no lag can be proven,
--allow-data-losspromotes the least-behind replica, after fencing the old primary, and the failover records it. Guardrails. - Ransomware canary response. A policy can pause its source on an alarm (
--pause-on-alarm), and events can be acknowledged, confirmed or dismissed on the overview or withtilldev ark canary. Dismissing a false positive needs an owner or admin and releases the backup from quarantine. Response. - Signed agent releases. The install script checks the release signature and checksum and stops if either fails; the agent guide shows how to verify by hand. Install.
tilldev ark sources rm --destroy-backupsnow says which backups stay readable: ones under a customer key can't be destroyed by TillArk, only by destroying the key or deleting them from storage.
September 2026 · TillArk: PostgreSQL to any moment
- Point-in-time recovery for PostgreSQL. Sources backed up with WAL-G now stream their write-ahead log to every target that holds their backups, so a real restore can land on any moment between the oldest WAL-G base backup and a few minutes ago. Pick A point in time on the Restores page, run
tilldev ark restore --source <id> --at <time>, or sendsource_idandtarget_timetoPOST /api/ark/restores. TillArk picks the newest base backup that can reach the moment, and the restore reports the last commit it replayed. A moment with no later commit, such as a quiet night, restores too. Point-in-time recovery. - See how far recovery reaches. Each WAL-G source shows, per target, the time every earlier commit is archived through, its lag, and any gap where WAL may have been lost, dated from the last moment the archive was proven complete. Also in
tilldev ark walandGET /api/ark/wal. After a gap, TillArk queues the base backup that closes it once the stream is back. - A restore that can't be done is refused with the reason: a moment in the future, before the backup finished, past what is archived, or across a gap. A WAL-G backup whose own WAL was lost is no longer restored for real.
- Breaking: WAL-G runs only on the database host. WAL-G backups go only to an agent that lists the source in
TILLARK_LOCAL_SOURCES, and only one agent may list it. The source's role needs theREPLICATIONattribute, a replication line inpg_hba.confandEXECUTEonpg_switch_wal(). WAL-G can't verify an SFTP server's host key, so it no longer uses SFTP targets. - Sources, targets and policies report when their configuration last changed (
updated_at), in the API, the dashboard and the CLI. - Schedules you can see. Policy schedules and verification cadences are cron in UTC, and a schedule that can never fire is refused when you save it. Missed slots run once as a single catch-up, and a slot that falls while a backup of the source is still running waits for it. Each policy shows its next run and, if a scheduled backup couldn't be queued, why: on the Policies page, in
tilldev ark policies ls, and asnext_run_atandschedule_errorin the API. A skipped slot is also in the audit log. Schedules and upkeep. tilldev ark policies get,updateandrm.updatechanges only the flags you pass, so--keep-daily 14leaves the other retention buckets as they were.- Fixed: a job whose agent restarted or stopped stayed running and blocked later backups of that source. The job is now marked failed with the reason: at once when the agent restarts, or after 10 minutes without word from it. Agents also retry a job's outcome through network errors instead of losing it.
- Fixed: with more than one target, retention counted a source's backups across all of them, so a target could keep fewer copies than the policy asked for. Each target now keeps its own full set.
- Fixed: deleting backups that retention no longer keeps could overlap a backup or restore on the same target. They now take turns, and a delete left by an agent that went away is taken over after 30 minutes.
- Fixed: deleting old backups could change the recorded finish time of a backup whose delete failed, which point-in-time recovery uses to pick a base backup.
September 2026 · iOS crashes, down to the line
- iOS and macOS crashes are symbolicated on the server. Upload your dSYMs and native frames (Swift, Objective-C, C and C++) show function, file and line, with inlined calls expanded and Swift and C++ names demangled. A dSYM is matched to crashes by build UUID, so it applies to every crash from that build. dSYMs guide.
- Upload dSYMs the way Xcode writes them.
tilldev pulse dsym uploadtakes a.dSYM, a folder or an.xcarchiveand uploads every dSYM in it, frameworks included. Files up to 1 GB go up in parts, a few at a time, with retries. The dashboard's dSYM tab takes a whole folder, and the API has the same upload in parts (POST /api/projects/:id/dsyms/uploads). - Breaking: a single-request dSYM upload (
POST /api/projects/:id/dsyms) now takes files up to 32 MB. Larger files upload in parts, which the CLI and the dashboard do for you.POST /api/projects/:id/source-mapsno longer acceptssymbolication_type=dsym; send dSYMs to/dsyms, which reads their build UUIDs. - Uploading an app binary instead of its dSYM now answers with a warning: without debug info, crashes resolve only to the symbols the binary exports, with no file or line.
- A new crash reporter for iOS and macOS, in React Native 0.3.0 and the Flutter SDK. It catches signals, Mach exceptions and uncaught Objective-C exceptions, follows Swift async calls back to the code that awaited them, and records what symbolication needs. App hangs are reported too: a stall that recovers is a medium-severity warning, one that lasts is high. Flutter macOS apps get the same reporter.
- Crashes group by where they crashed. An issue is now keyed on the app frames nearest the crash, after symbolication, rather than the ones where the stack began. Existing issues carry on under the new grouping instead of splitting.
- Fixed: in React Native, a fatal JavaScript error could be lost when the app closed before it was saved. The SDK now saves it before React Native ends the app, and reports it as critical.
- Fixed: in React Native, events captured while the app was starting could be dropped when the queue left from the previous launch loaded. Both are kept, oldest first.
- API keys are checked on symbol files. Listing source maps, ProGuard mappings and dSYMs needs
pulse.projects.read; uploading or deleting them needspulse.projects.write; a key pinned to projects reaches only those. A project outside your organisation answers 404. - Fixed: deleting one architecture of a multi-architecture dSYM deleted the file the others used, so their crashes stopped symbolicating.
- Fixed: changes to projects, releases and issues, password changes, and actions taken with an API key were missing from the audit log.
September 2026 · TillNotary
- A new product: TillNotary, a tamper-evident transparency log. Submit a hash and get back a signed inclusion proof and a witness-cosigned timestamp that you verify yourself, against keys you pinned, online or with no network. Nothing is tamper-proof: a rewrite can't be prevented, but anyone holding an earlier proof can detect it. Quickstart.
- Your own witness in the quorum. TillDev runs a platform witness with its own key. Run yours with
tilldev notary witness-nodeand require its cosignature, so no checkpoint completes without you. A witness refuses a head that doesn't extend the last one it cosigned, publishes a signed refusal, and the org's owners and admins are emailed. - Mirrors.
tilldev notary mirrorkeeps a full copy of a log in which every entry must rebuild the signed root, and exits 3 with the conflicting signed heads saved if the log shrinks, forks or rewrites history. The Node SDK has the same in@tillstack/sdk-notary-node/mirror. - Post-quantum signatures. Checkpoints carry hybrid Ed25519 + ML-DSA (FIPS 204) signatures, and both must verify. The government suite uses SHA-384 + ML-DSA-87, at the CNSA 2.0 algorithm levels. A log's suite is fixed at creation.
- Evidence bundles verify offline (
tilldev notary verify bundle.json); look an entry up by its value (tilldev notary lookup); mint scoped, expiring submit tokens in the dashboard or withtilldev notary tokens. Everything is in the CLI, a verifying Node SDK (@tillstack/sdk-notary-node) and an OpenAPI-described REST API. Full TillNotary changelog.
September 2026 · From a crash to the change behind it
- Suspect changes for every release. A repository's new Crashes tab lists the releases that shipped its commits. Pick one to see its crash-free rate against the release before it, and the pull requests and commits in between ranked by how closely their changed files match the stacks of crashes new in that release. From the terminal:
tilldev forge correlation <repo> --release <version>. It is a ranking to start from, not a verdict. How it works. - New crashes reach the person who changed the code. Link a repository to a TillPulse project (repo Settings → TillPulse project, or
tilldev forge repos update <repo> --pulse-project <project>) and its pushes feed crash ownership: a new crash group is attributed to whoever last changed the file where it crashed, and they get a notification, plus an email unless they have turned forge emails off. - Review pull requests in VS Code. The TillForge extension opens a pull request's files as diffs; comment on lines, reply in threads, then approve or request changes. Lines that appear in open crash stacks show “crashed N× in prod”, with the crash groups and who last changed the line on hover.
- Line comments follow their line. Push more commits or rebase and a pull request comment moves with the line it was left on. If that line changes, the comment is marked outdated rather than lost.
- Fixed: pull requests from a branch in the same repository ignored pushes made after they were opened. The diff kept showing the first version, the pull request's checks did not re-run, and, because the default policy counts only approvals of the current head, an approval given after a push was never counted and the merge stayed blocked. Pull requests now track their branch, and reviews record the commit they approved.
- Reviewers, comment authors, issue authors and assignees now show by name in the dashboard, the CLI and the API (
author_name,reviewer_name,assignee_name) instead of as an id. tilldev forge reflog <repo> --ref <branch>narrows the history to one branch and shows who made each change.tilldev forge recoverreturns the branch to where it was before the change you pick.- Fixed: crash ownership was worked out from the frames where a stack began (often the app's entry point) rather than where it crashed.
- Fixed: releases recorded with a short commit sha never matched their commits in TillForge, and the crash-free figure on a repository's overview never appeared.
- Fixed: the issue links in alert emails and in Slack, PagerDuty and Teams messages opened a page that did not exist. They now open the issue.
- Fixed: files that would not open in TillForge. A file that failed to load showed an empty panel, or the file opened before it under the new name. In the web editor the error text became an unsaved change that could be committed. Both now show the error with a retry. ✎ Editor on a file in the Code tab opens it in the editor, and switching branch there re-reads open files from the new branch.
- Fixed: in the CLI, a flag that takes no value, such as
--jsonor--yes, swallowed the word after it, sotilldev notary attach --json my-log …lost the log name. - CLI 0.8.0: names instead of ids. Secrets projects and environments, cache namespaces and TillPulse projects accept a slug, and a secret accepts its key with
--env:tilldev secrets rollback API_KEY --env prodreturns it to the previous version. When an environment slug exists in several projects the CLI asks for--projectrather than guessing.tilldev secrets sync addreads the provider config from stdin with--config-stdin.
September 2026 · SDKs and docs that agree
- Code samples you can paste. Every sample in the docs and in each npm package's README is now checked against the SDK it uses, so none names a method, option or argument that doesn't exist. Samples were corrected across the Flutter, React Native, TillAuth, TillNotary, TillShield, TillSecrets and TillCache docs.
- Flutter SDK ready for pub.dev (
tillpulse). The Flutter guide was rewritten against the real API. New:TillPulseNavigatorObserverfor navigation breadcrumbs, andTillPulse.captureZonedErrorfor apps that own their zone.enableNetworkTracking,networkUrlDenylistandmaxDailyDataKbwere accepted but ignored; they now work. Flutter guide. - React Native 0.3.0.
maxDailyDataKBis now a real per-day cap that survives restarts; it was a per-session count. Past the cap, only errors, pre-crash snapshots and session markers are sent. The SDK no longer records its own uploads as network breadcrumbs. Five options that never did anything are marked deprecated. React Native guide. - Fixed: the browser, Electron and React Native SDKs reported themselves as version 0.1.0 on every event. The version now comes from the package at build time.
- TillCache sorted sets, and full commands on the Durable Objects backend.
zadd,zincrby,zrange,zrevrange,zrank,zscore,zcountand friends are available for leaderboards and ordered indexes, alongside typed set methods. Namespaces on thedurablebackend previously rejected about half of the allowed commands (SETNX,GETDEL,HMGET, sets and more); they now answer all of them the way Redis does. KV guide. - Breaking: SDKs refuse to send a token over plain http.
@tillstack/secrets-*0.4.0 and@tillstack/cache-*0.3.0 now require https for any host other than localhost, matching the CLI and the TillNotary SDK. - Fixed:
createClient({ leaseUrl })in@tillstack/secrets-nodesilently droppedleaseUrl. It is honoured now, and so isTILLSECRETS_LEASE_URL. - CLI 0.8.0. Password and secret prompts show one
*per character, so you can see what you've typed. SetTILLDEV_PROMPT_ECHO=offto hide even that. Arrow keys no longer inject escape codes into a secret, a pasted value ending in a newline submits cleanly, and a hidden prompt never echoes into redirected output. - Every npm package now has a README, and each README states the license the package actually ships under (Apache-2.0; some said MIT).
- TillAuth webhooks: verify in one call, replay from the log.
verifyWebhookin@tillstack/auth-node0.4.0 checks the signature and timestamp over the raw body and returns the typed event. The webhooks guide had the wrong header names, payload shape and retry schedule; it now matches what is sent: six attempts over about 12 hours (immediately, then after 1m, 5m, 25m, 2h and 10h). Any finished delivery can be replayed from the dashboard or the API. Webhooks guide. - Fixed: an endpoint subscribed to a misspelt event name was saved and then never fired. Unknown names are now rejected, and the event picker lists the push sign-in and device events it was missing.
- TillCache subscribers resume after a reconnect. Streams rotate about once a minute, and
subscribepreviously stopped at the first rotation. It now reconnects on its own and picks up after the last message it saw (each channel keeps its last 1,000), backs off on errors, and rejects only on a permanent error such as a bad token. The docs now say whatpublish'sdeliveredmeans: stored, not a count of listeners. Needs@tillstack/cache-*0.3.0. Pub/sub guide. - Fixed: uploaded source maps and ProGuard mappings were not being used to symbolicate stack traces, so frames stayed minified. Upload again any maps for releases you still need symbolicated. Source maps.
- The support assistant now answers questions about all nine products. It no longer quotes prices; ask support@tilldev.dev.
September 2026 · TillForge CI secrets
- CI jobs can use TillSecrets. Bind one TillSecrets environment to a repository (
tilldev forge ci secrets bindor the Secrets panel on the CI tab), then list the keys a job needs undersecrets:in its ci.yml. Only those keys are decrypted, at claim time, and every delivery lands in the TillSecrets audit log. How it works. - By default only pushes to protected branches receive secrets. Manual runs and re-runs get them only for a commit already on their branch, same-repo pull requests only when the binding allows all refs, and code from forks never does. A refused job ends as
errorwith the reason in its log rather than running without them. - Breaking: credential-bearing jobs run only on secrets runners. Jobs that declare secrets, and every deploy, are now claimed only by a runner registered with
--secrets(or the checkbox on Forge → Runners), and such a runner runs nothing else, so a pull request can never share a machine with a credential. Deploys wait as awaiting secrets runner until your org registers one on its own machine. - Runner 2.
tillforge-runnernow passes secret values outside the process list and masks them in the job log, including each line of a multi-line value. Deploy credentials take the same path. Older runners keep working but are never given secrets. - Fixed:
tilldev forge ci run --shawith a short sha enqueued jobs every runner refused; the sha is now resolved to the full commit first. - Fixed: the TillForge device sign-in rate limit was shared by every user rather than applied per address. The status page now also reports the queue and cache layer.
- Faster pages. Docs, product, legal and changelog pages were rendered on every visit; they are now served from cache and refreshed in the background every five minutes.
- Faster ingest. Accepted events are acknowledged sooner.
August 2026 · TillForge CI: services, and a container that can drop privileges
- Jobs can declare service containers. A test suite that needs a database says so: up to five
services:per job, each on a private network created for that run, reachable at the service name as a hostname (db:5432). Nothing is published to the host, no service sees your workspace, and they are torn down with the job — including when it is cancelled or times out. Aready:command is polled inside the service until it passes, and a service that never comes up fails the job with its own log attached rather than a bare timeout. CI documentation. - Official images work now. Job containers previously dropped every Linux capability, including the two an image entrypoint needs to stop being root. Since postgres, mysql, redis, elasticsearch and nginx all start as root and switch user via
su-exec/gosu, they died on a message about the entrypoint that named neither the cause nor the fix. Those capabilities are back;no-new-privilegesstill blocks escalation in the other direction, which is the one that mattered. - Breaking: jobs no longer run as root by default. A job now runs as the workspace owner, so
/workis writable and the copy-the-checkout-first step every config carried is unnecessary. Steps that install into the image (apt-get,apk add,pip install) needuser: rooton that job. Runner operators can restore the old fleet-wide behaviour withTILLFORGE_RUNNER_JOB_USER=root. - A failing container whose output shows a privilege-drop refusal now gets the cause named in the job log and on the failure reason, instead of leaving you to reproduce the runner's flag set by hand to find it.
July 2026 · The Access Centre
- App settings are scriptable.
tilldev auth apps updatechanges MFA enforcement, unverified-sign-in, redirect origins and the rest from CI or a setup script — the settings that previously existed only in the dashboard. Partial by design: flags you omit keep their value, and the same policy guards apply (a change that would strand users is refused with a count). - Duplicate sign-ups are no longer a dead end. Signing up with an address that already has an account still returns a deliberately non-enumerating response — but the address's real owner now gets an “you already have an account” email pointing at sign-in and password reset (throttled, and customisable like every other TillAuth email).
- Hash-preserving user migration for TillAuth. Bring an existing user base over without forcing a single password reset: SCIM
POST /Usersand a new bulk/admin/apps/<id>/users/importendpoint accept legacy bcrypt and pbkdf2 hashes verbatim, sign-in verifies against them, and each user is transparently upgraded to Argon2id on their first successful sign-in. Provisioning guide → Migration. - Per-member access grants across every product. Inviting or editing a developer/viewer now scopes them to specific TillAuth apps, Forge repositories, projects (Pulse & Shield), cache namespaces and secrets projects . A member with no grants for a product can see all of it; add a grant to narrow that. API tokens pin to the same resources.
- TillShield edge keys: the API, CLI and docs now say the key belongs to a TillPulse project, and show the commands to create one.
- Fixed: freshly created projects could render their DSN against a development ingest host. Existing projects now show the correct DSN, with no key rotation needed.
July 2026 · Identity pipeline + the API platform
- TillAuth end-user API published as OpenAPI 3.1 —
auth.tilldev.dev/openapi.json, checked against the live API so it stays accurate. New guides: API reference, embedded account settings, Workers + edge verification. - Accounts without a password can set one from a signed-in session. The hosted
/securitypage lists the account's password, passkeys (and unlocks a locked one), authenticator app and remaining backup codes. Removing a sign-in method that would lock you out is refused, with the reason. - Platform API tokens with
product.resource.actionscopes, resource pinning, IP conditions and expiry, plusGET /api/tokens/verify. TillAuth admin endpoints enforce these scopes. - TillShield inline WAF: Workers wiring guide . The WAF keeps enforcing its last rules if it can't reach TillShield, with no added latency.
- TillForge device flow returns you to the approval screen after login; the TillSecrets docs cover injecting secrets at deploy time.
v1.0 — May 2026 · Public launch
- Public landing site, documentation, legal pages, and SEO.
- A new visual design.
- Status: production.
April 2026 · Redesign
- A new dashboard design.
- New pages: Alerts (fired alerts and rules), Ask Pulse multi-turn chat, a Field Map of where users are, Releases with side-by-side compare, and TillMind hypothesis cards.
- Ask Pulse answers stream as they are written.
April 2026 · Performance, security and integrations
- App-start timing (cold and warm) and frame jank (slow and frozen frames) on iOS and Android, for React Native and Flutter.
- Threat intel shared across customers as hashed indicators only.
- Single sign-on via OIDC, with users created on first sign-in.
- Linear and Jira integrations with two-way status sync.
- CLI uploads for releases, source maps, ProGuard mappings and dSYMs.
- A mobile companion app for triage on the go.
March 2026 · Alerting and device signals
- Branded email alerts.
critical_pathalert trigger with glob matching.- PagerDuty and Microsoft Teams alert actions.
- Devices and Security pages.
- Battery use attributed per screen.
- Root and jailbreak detection on React Native and Flutter, and overlay-attack detection on Android.
- Ask Pulse: questions in plain language, answered with read-only queries scoped to your project.
February 2026 · Integrations
- Slack alerts with Resolve, Ignore and View buttons.
- Upload source maps, ProGuard mappings and dSYMs from project settings.
- Connect a GitHub repository and manage its webhook secret.
- Release health: crash-free percentage and an A–F grade per release.
January 2026 · Deeper symbols
- ProGuard and R8 mapping support for Android stack traces.
- iOS dSYM upload.
- GitHub push events link commits to releases, and issues get a suggested owner from blame.
- A five-step onboarding that waits for your first event.
December 2025 · Native crashes
- Native crash capture on iOS and Android for React Native and Flutter.
- Out-of-memory detection, reported on the next launch.
- Release tracking.
- Issue assignment and threaded comments.
November 2025 · Performance and search
- Performance tracking: transactions, spans, sampling, and p50/p95/p99.
- Full-text issue search.
November 2025 · AI and symbols
- TillMind: an AI hypothesis on every new issue and regression.
- JavaScript source-map symbolication.
- Location enrichment for events.
- Team invites and password reset by email.
- Flutter SDK with the same features as React Native.
October 2025 · Public alpha
- Event ingest with DSN authentication, rate limits and PII scrubbing.
- Issue grouping and alerts.
@tillstack/react-nativeSDK with an offline queue, breadcrumbs, friction detection and abeforeSendhook.- The dashboard: overview, issues, alerts and settings.
See the docs for how to use each product.