A forward deploy of an existing release now gets the pre-migration snapshot
Measure the step, not the label
fixeddeployoperators
deploy.sh --version was treated as a rollback, so shipping an already-cut release forward applied its migrations with no pre-migration snapshot and no honest rollback. The snapshot now keys on the migrations the deploy actually applies.
#3690
· 2026-10-20
A browser's slot and identity stay held until its end is confirmed
Nothing is free until it is seen gone
fixednodeoperatorsdevelopers
If a client disconnected while a session was ending, the node could count that browser's slot as free before the browser was confirmed gone, and a retried end could let the identity go too early. Both now wait for a confirmed end.
#3704
· 2026-10-17
Control ends abandoned sessions and sees which ends are unconfirmed
Say what you see
fixedcontroloperators
A session the node has abandoned for inactivity is now ended by control instead of staying live while its lease renews. Its identity stays held until the node confirms its browser is gone.
#3707
· 2026-10-20
v2026.10.17.3
2026-10-17
An ended session never starts or launches a browser again
Ended stays ended
fixednodedevelopersoperators
When a session ends or is abandoned, the node records that durably. A later launch answers E_BROWSER_UNAVAILABLE with reason session_ended, and a delayed or retried start of it is refused, also after a node restart.
addednodeoperators
The node's GET /health now answers 503 with reason barrier_unreadable when its record of ended sessions cannot be read; the node then refuses every start and launch but keeps ending sessions.
#3684
· 2026-10-17
v2026.10.17.2
2026-10-17
The node's session cap now counts browsers, not sessions
Count what holds the room
changednodedevelopersoperators
The node's cap now counts browsers, from launch until their end is confirmed, crashes included. A session with no browser, such as a parked or abandoned one, takes no place, and a refusal says limit runningBrowsers.
#3687
· 2026-10-17
A warm resume refused for capacity keeps its sign-in for the retry
A refused door keeps your key
fixednodedevelopers
When a warm-resume session's first browser launch was refused, for example because the node was at its browser cap, the saved sign-in was already used up, so the retry opened a cold session. The node now keeps it until a launch succeeds.
#3700
· 2026-10-17
v2026.10.17.1
2026-10-17
A session's identity is freed only once its browser is seen to be gone
Watch it go before you let it go
fixednodedevelopersoperators
Ending a session now checks that every process of its browser is gone before the session counts as ended. Until then it stays draining and keeps its identity, so no other session can take it while the browser may still run.
#3679
· 2026-10-09
Control's health check also reports whether the node is healthy
Up means the part that does the work is up
addedcontroloperators
The health endpoint's body now carries a node field: ok, or a short reason such as unreachable or timeout. Before, it checked only the database, so a down node still read as healthy.
#3686
· 2026-10-09
The MCP lease-release tool runs its workflow instead of failing with 400
An empty request asks for nothing
fixedmcpdevelopers
identity_release_lease answered 400 (missing field declaredEvidence) on every call. The gateway sends an empty JSON object, and the route read any body as the declared override; an empty object now runs the ordinary release workflow.
#3694
· 2026-10-17
A full node now says so: session starts answer a retriable 503, not a 502
Full is not broken
fixedcontroldevelopersoperators
When the node is at its live-session cap, a session start now answers 503 E_NODE_CAPACITY (retriable, NOT_STARTED) with a Retry-After header, instead of 502 E_UPSTREAM.
#3695
· 2026-10-17
v2026.10.08.2
2026-10-09
wait now tells visible from mounted, and absent from not-found-yet
A wait that answers the question asked
fixednodedevelopers
The typed wait's selector states now mean what they say: visible needs a rendered element, hidden and detached are satisfied by an absent one, and a selector that matches several elements is no longer stuck as not satisfied.
#3665
· 2026-10-08
A session keeps its network log tier and viewport across a node restart
What you declared stays declared
fixednodedevelopersoperators
A session started with its network log off now stays off after a node restart. It used to come back at the metadata tier and start recording method, host, path and status. A higher tier is kept too, and so is the requested viewport.
#3666
· 2026-10-08
The abandoned-session refusal reads as one sentence
Close the gap
fixednodedevelopers
The message on a session_abandoned refusal carried a run of 18 spaces in the middle of its sentence; it now reads as one line.
#3674
· 2026-10-08
v2026.10.08.1
2026-10-08
Frontend deploys show why a build failed instead of discarding it
A quiet build still speaks when it fails
fixeddeployoperators
The console, docs and website deploys stay quiet while a build succeeds, but when it fails they now print the last 40 lines of the build and the path to its full log, so the deploy log names the cause.
#3639
· 2026-10-01
The changelog files each change under the release that actually shipped it
Shipped means contained
fixeddocsoperatorsdevelopers
The changelog now lists each change under the first release that actually contains it. It grouped by day, so a change merged after a day's last release read as shipped in that day's first one.
fixedconsoleoperators
The What's new banner no longer says the changelog is older than the running build when the server runs a recent release. The banner matches the running version to the changelog's releases, and same-day releases were missing.
A console whose server reports v2026.10.01.5. Before: a banner claiming the changelog is older than the running build, because that release had no section. After: no banner, because it has one. Captured from a local build.
#3643
· 2026-10-01
The hosted node gets 12 GiB of memory, up from 8
Room for the tabs the sessions open
fixeddeployoperators
On 2026-10-08 seven cloak sessions with ChatGPT tabs outgrew the node's 8 GiB memory cap: the node thrashed, renderers were OOM-killed, and perceive timed out. The hosted node's cap is now 12 GiB.
#3656
· 2026-10-08
Dialogs keep a margin from the screen edge on a narrow screen
A frame needs its margin
fixedconsoleoperators
On a phone-width screen, a dialog such as Create API key filled the screen edge to edge. It now keeps a margin on every side.
The Create API key dialog at a 400px wide viewport. Before: the panel touches both edges. After: a margin on every side. Captured from a local build.
#3657
· 2026-10-08
An off-box probe now raises an issue when production goes down
Watch from outside the house
addeddeployoperators
A scheduled probe checks the production health endpoint from outside every 15 minutes and opens a prod-down issue when it stays unreachable, closing it on recovery. A 28-hour outage in October went unnoticed because no alert path existed.
#3658
· 2026-10-08
Confirmations use the shared nightglass toast and can be dismissed
Said once, then out of the way
changedconsoleoperators
The small confirmations that appear after an action, such as Session ended with the session's id, now use the nightglass toast. Each has a close button and is drawn above any open dialog.
The Session ended confirmation after ending a session. Before: the console's own toast. After: the nightglass toast, with a close button. Captured from a local build.
#3659
· 2026-10-08
An abandoned session now says it was abandoned
Name the timer, not the tunnel
changednodedevelopersoperators
A session the node abandoned after its inactivity timeout (30 min by default) now answers later calls with E_BROWSER_UNAVAILABLE and reason session_abandoned, not proxy_not_registered, which pointed at the proxy instead of the timer.
#3660
· 2026-10-08
A screen reader hears each sign-up attestation in full
What you read is what you agree to
fixedconsoleoperators
On the create-organization page, each checkbox is now announced with exactly the text beside it. The business attestation used to be announced without its last sentence, about being authorized to bind the organization.
The create-organization page, where the three attestation checkboxes are now named by their full visible text. Captured from a local build.
#3661
· 2026-10-08
A role locator finds native buttons, links and inputs, not only explicit roles
A button is a button without saying so
fixednodedevelopers
A quoted, exact role locator for a button named X now finds a native button, link or input with that accessible name. Before, it saw only elements with an explicit role attribute, so on most pages it timed out as not found.
#3664
· 2026-10-08
v2026.10.01.6
2026-10-01
A session that refuses to launch its browser says so on every call
Ask twice, hear the same answer
fixednodedevelopersoperators
When a session refuses to launch its browser, every page call on it now returns that same refusal with its reason. Before, only the first call did, and later calls returned E_TAB_NF, which reads as navigate first and can never work.
#3635
· 2026-10-01
v2026.10.01.5
2026-10-01
An ended session no longer leaves its identity stuck as in use
Once ending, never attached again
fixedcontroloperators
A background cleanup could mark an identity as in use again just after its session ended, so every new session on it was refused until someone force-released it. A lease that is ending now always finishes ending.
#3625
· 2026-10-01
Sessions keep working across a node restart, inside their original limits
The envelope travels with the session
securitynodeoperatorsdevelopers
A session the node rebuilds after a restart, such as a deploy, now gets its exact egress policy back and relaunches its browser through its own proxy. Before, it was refused with envelope_not_restored and had to be replaced.
securitydeployoperators
New node setting NIGHTJAR_REQUIRE_SESSION_EGRESS, on in the hosted deploy: every browser launch must go through a session proxy, or it is refused with proxy_not_registered. The node logs whether it is enabled or disabled at boot.
#3630
· 2026-10-01
A session that refuses to relaunch its browser now says why
One code, two causes, and now a reason to tell them apart
fixedcontroldevelopersoperators
When a session can no longer launch its browser, for example after a node restart, the API error now carries a reason such as envelope_not_restored. Before, it looked the same as a node with no browser installed.
#3632
· 2026-10-01
v2026.10.01.4
2026-10-01
The console never shows an identity as free when it cannot read the lease
Not knowing is not the same as free
fixedconsoleoperators
When the control plane does not report an identity's lease, the console now says Lease unknown and blocks deleting it, instead of showing it as Available.
The identities list, where the Lease column lives. On a current control plane it looks exactly as before; Lease unknown appears only when the control plane does not report the lease.
#3609
· 2026-10-01
The identity response says available or in use, like the assumable list
One word for held, on every surface
addedcontroldevelopers
The identity list and single-identity responses on /v1 now return leaseState, available or in_use, the same value the assumable list already returns for the same identity.
#3612
· 2026-10-01
Every identity lease release now leaves an audit record
No release goes unrecorded
fixedcontroloperators
An org suspend, and the cleanup that finishes an end the node confirmed later, now record the identity lease they release, with no actor and a via field naming the path.
#3619
· 2026-10-01
Sessions refuse to relaunch outside their limits after a node restart
Refuse rather than run outside the bounds
securitynodeoperatorsdevelopers
After a node restart, such as a deploy, a live session's browser relaunched without its egress proxy and limits, and cloak relaunched as Chrome. Such a session now refuses its next command with a typed error; start a new one.
changedcontroldevelopers
launchedBrowserKind now describes the running browser: a relaunch updates it with a new launchConfirmedAt, and after a node restart it is absent until the relaunch is confirmed. Absent means not yet confirmed, never a match.
#3620
· 2026-10-01
v2026.10.01.3
2026-10-01
One identity, one browser, even under concurrent starts and unconfirmed ends
One identity, one browser at a time
fixedcontroldevelopersoperators
Two session starts on the same identity can no longer both succeed. The second is refused with 409 E_CONFLICT, and its reason says why the identity is held.
addedcontroldevelopers
Identity responses gain leaseHold: live, in_flight, ending or unresolved, and null when the identity is free. A refused session start names the same value in reason. leaseState stays available or in_use.
changedcontroldevelopersoperators
Force-release now ends the session and frees the identity only once the node confirms the browser is gone. Otherwise the lease stays, and released: false says why.
changedcontroldevelopersoperators
Ending, deleting or suspending a session that holds an identity completes it only once the node confirms. Until then the session is draining: it cannot be driven, and the identity stays held.
addedcontroloperators
A reconciliation worker, on by default, finishes interrupted starts and unconfirmed ends once the node confirms. Its boot line says whether it is running.
addedcontroldevelopers
A new 503 E_BIND_BUSY, retriable and with Retry-After, is returned when every identity-start slot is in use.
changedmcpdevelopers
identity_list_assumable shows leaseHold, and identity_release_lease runs the termination workflow and reports a reason when it keeps the lease.
fixedconsoleoperators
An identity held by a start in progress, or by one that was interrupted, now reads In use instead of Available.
The identities list: ops-runner is held by an interrupted start with no session yet. It used to read Available; it now reads In use.
#3597
· 2026-10-01
Governance docs stop saying recording and cloak mirror local reach
Two switches that still start off
docscontroloperatorsdevelopers
The allowSessionRecording and cloakEnabled descriptions in the governance contract said they were off by default, mirroring allowAgentSelfReach. New orgs now get allowAgentSelfReach on, so the two descriptions name each other instead.
#3600
· 2026-10-01
v2026.10.01.2
2026-10-01
Agent keys in new orgs can ask for local reach by default
Asking is open; reaching still needs a human
changedcontroloperatorsdevelopers
In an org created from now on, an agent-bound key minted without scopes carries reach:self, so its agent can ask for local reach without an admin first enabling allow_agent_self_reach. Existing orgs keep their stored setting.
#3590
· 2026-10-01
A crashed session no longer holds its identity forever
Ask the node who is still alive
fixedcontroldevelopersoperators
Since v2026.10.01.1 a session whose browser had crashed could keep its identity held: the reaper waited for a confirmation the node never gave. It now treats a session missing from the node's live list as ended, and frees the identity.
#3591
· 2026-10-01
v2026.10.01.1
2026-10-01
The act receipt no longer promises a join key it does not deliver
Declared is not delivered
docssdkdevelopers
ActReceipt.commandSpanId is now described as absent when unset, never null, and as not yet delivered on act receipts, so no client builds a correlation chain on a key that is always missing today.
docsmcpdevelopers
The act tool's receipt schema carries the same correction: commandSpanId is absent rather than null, and is not yet populated on act receipts.
#3508
· 2026-09-29
An identity's lease holder is reported the way a bind sees it
One predicate, read and write alike
fixedcontroldevelopersoperators
The identity read now reports leaseHeldBy whenever a live session holds the lease, including after its renewal horizon has passed. It used to read null there while session_start still refused the identity.
addedcontroldevelopers
Identity reads carry leaseExpiresAt, the held lease's renewal horizon, so a holder can renew before it passes. It is null exactly when leaseHeldBy is, and a past value does not mean the identity is free.
#3515
· 2026-09-29
Identity page stops claiming a snapshot is captured when a session ends
Only a capture you ask for becomes a snapshot
fixedconsoleoperators
The identity page said a login snapshot is minted when a session ends; nothing does that. It now says snapshots come only from an explicit capture, and marks the version warm-resume actually uses.
The auth-state versions section, before and after: the corrected explanation, and the active chip on the version warm-resume uses.
#3520
· 2026-09-29
See who approved or denied each access request, and when
Every decision keeps its decider
addedcontroldevelopersoperators
GET /v1/access-requests takes a status filter, and every approved or denied request now names who decided it (actionedBy) and when (actionedAt).
addedsdkdevelopers
accessRequests.history() pages through approved and denied access requests with their deciders; accessRequests.list() still returns the pending queue exactly as before.
addedconsoleoperators
The Identities screen shows Recent decisions under the access-request queue, so an approval no longer vanishes from the console once it is made.
#3525
· 2026-09-29
Clipboard capture resolves perceived controls; errors stop naming other tabs
Copy the control you perceived
fixednodedevelopers
clipboard_capture now resolves a perceive address for its copy control, the same way act does, generation suffix and all. It used to fail every time with not found in perception snapshot, whatever the page.
securitynodeoperatorsdevelopers
A not-found error for a uid or a tab no longer lists the tab ids and UID counts of other sessions on the same node. It names only the tab it was asked about.
#3526
· 2026-09-29
Session terminalReason says what it reports today
Over is not the same as clean
docscontroldevelopers
The terminalReason description now says that every terminal session currently reads ended, crashed, evicted and challenge-walled ones included, since nothing records a reason yet. Read ended as “the session is over”, not “it ended cleanly”.
#3531
· 2026-09-29
The adopt route names the takeover scope and when it applies
Say which door needs the second key
docscontroldevelopers
POST /v1/sessions/:sessionId/adopt now names sessions:takeover: replacing another principal’s live controller token, or a live input grab someone else holds, needs org-admin membership or that scope, and otherwise answers 403.
#3533
· 2026-09-29
The command palette puts your cursor in the search box again
Type the moment it opens
fixedconsoleoperators
Opening the command palette with Control-K or Command-K focused its Close button instead of the search box, so typing went nowhere. The search box has focus again.
The command palette just after Control-K or Command-K: what you type lands in its search box.
#3534
· 2026-09-29
The crashed-session reaper no longer ends a session that started mid-check
Choose who to check before you look
fixedcontroloperators
The crashed-session reaper now picks its candidate sessions before it asks the node which sessions are alive, so a session that starts during that check can no longer be ended as crashed.
#3536
· 2026-09-29
Reapers free an identity lease only when the node confirms the browser ended
No release without a receipt
fixedcontroloperators
The session reapers now end a session and free its identity lease only when the node confirms the browser is gone. An unreachable node leaves the session live and the lease held until a later tick can confirm.
#3537
· 2026-09-29
The role selector says how it matches a name
First match wins, and now it says so
docscontroldevelopers
The act selector description now says how a role locator's name matches: a case-insensitive substring, and the first match in accessibility-tree order wins with no ambiguity error. A name like Copy also hits an earlier Copy message button.
docsmcpdevelopers
The act tool's selector description in the MCP schema carries the same matching rule, and points to the perceive address when two controls share a name.
#3540
· 2026-09-29
A quoted locator name matches exactly, and refuses when it is ambiguous
Say exactly which one, or hear that there are two
addednodedevelopers
A quoted name or text in a role, text, label or placeholder locator now matches exactly and case-sensitively. If an exact locator matches more than one element, nothing is done and E_LOCATOR_AMBIGUOUS names each candidate's uid.
addedmcpdevelopers
The act, wait, extract and clipboard capture tools accept the quoted exact form in their selectors, with the same refusal when it matches more than one element.
#3542
· 2026-09-29
Issuing, revoking and expiring a reach grant now leave an audit record
Who could reach what, and until when
addedcontroloperators
A reach grant's issue, its owner's revoke and its expiry each write a value-free entity event: the target policy, the owner and the actor, never a claim code. Before, the only record was the grant row itself, deleted 90 days after it ended.
#3543
· 2026-09-29
An ended reach grant's network stays guarded until it is actually cut
No reach without a live grant behind it
securitycontroloperatorsdevelopers
A reach grant's backing network is now torn down whichever path ends the grant, and stays guarded until it is cut. Before, after a re-ensure or before the reaper's next tick, another org member could bind it and reach the owner's target.
#3545
· 2026-09-29
Governance settings that nothing enforces now say so
A switch wired to nothing says so
fixedconsoleoperators
Settings no longer presents Data region as a residency choice: it says nothing in the platform acts on it yet. The Crypto-delete line says the flag is not read, and that purging a deleted org destroys its key either way.
The Data region field on Settings, Data governance: it now says the setting is not enforced.
docscontroldevelopersoperators
The governance fields dataRegion, operatorAccess and cryptoDelete are documented as stored but not enforced, on both the settings and the patch shapes. Their behaviour is unchanged.
#3547
· 2026-09-29
An act addressed by name says how many elements matched, and which one it used
It chose one of three, and said so
addednodedevelopers
An act addressed by a role, text, label or placeholder locator now reports receipt.matchCount, how many elements that locator matched. Over 1, an A_LOCATOR_MATCHED_SEVERAL advisory on the delta names the element used and the others.
addedmcpdevelopers
The act and credential fill tools publish receipt.matchCount in their output schemas, and the selector description says where the count and the advisory appear.
#3550
· 2026-09-29
Session list filters are declared, and an unknown status is now a 400
Two names, one status, no quiet typos
fixedcontroldevelopers
Filtering the session list by the completed status now returns every session the API reports as completed, including older ones stored under the legacy value ended, which the filter used to miss.
changedcontroldevelopers
Both session list endpoints now declare their query filters. A status other than live, completed, failed, queued or draining is a 400 instead of an empty list, so a mistyped status no longer looks like no sessions.
#3552
· 2026-09-29
The API reference stops advertising the retired mailbox credential kind
A retired kind says never, not yet
docscontroldevelopers
CredentialKind no longer describes mailbox as a working email-code fetch. It says the kind was retired on 2026-07-14, is refused at create, and stays in the enum only so older credentials still read.
fixedcontroldevelopers
Filling a stored mailbox credential is still refused, but the error now says the kind was retired and will never fill, instead of suggesting a resolver ships later. Other kinds keep their not yet fillable error.
#3554
· 2026-09-29
Nine error and approval messages lose a run of stray spaces mid-sentence
One space between words, not twenty
fixedcontroldevelopersoperators
The sign-in approval page, the reach refusal receipt and the declared-hosts error no longer show 13 to 45 spaces in the middle of a sentence. The ruled words of the receipt are unchanged.
fixedclidevelopers
The daemon's could-not-determine-a-control-URL error reads as one sentence again.
#3555
· 2026-09-29
Docs write every Bitspark project name as its repository is named
A name reads the way it is typed
docsdocsdevelopersoperators
The docs, READMEs and agent guides now write nightjar, nightfall and the other Bitspark projects exactly as their repositories are named, following the Bitspark naming rule. Quotations and verbatim records keep their original spelling.
internaldocsdevelopers
A new advisory CI job runs the vendored Bitspark naming check on every pull request, after a control that proves it flags a planted misspelling by name.
#3557
· 2026-09-29
The console, docs site and packages write the product name as nightjar
The name on the screen is the name you type
changedconsoleoperators
Console copy, page titles and the logo's accessible name now write the product as nightjar, following the Bitspark naming rule. HTTP header names such as X-Nightjar-Org are identifiers and are unchanged.
The What we store page: its body text and the topbar version label now read nightjar. Headings render in capitals, so they look the same.
docsdocsdevelopersoperators
The docs site's pages, navigation and llms.txt write nightjar. One error line keeps the capital, because it quotes the tunnel's output verbatim and that output is unchanged.
docssdkdevelopers
The npm package descriptions and source comments of the SDK, the API types, the design system and the UI components write nightjar. No exported name or behaviour changes.
#3558
· 2026-09-29
CLI help, CLI errors and MCP tool descriptions write the name as nightjar
The help text spells the name you type
changedclidevelopersoperators
The nightjar CLI's command help, error messages and remediation hints now write the product as nightjar, for example: Cannot reach nightjar server. Error codes and exit behaviour are unchanged.
docsmcpdevelopers
Five MCP tool descriptions now write nightjar: the egress argument of session_start and spawn_and_start_session, and console_log, network_log and local_reach_ensure. No tool name, argument or behaviour changes.
#3559
· 2026-09-29
The design-phase architecture docs are labelled historical
A frozen page says when it froze
docsdocsdevelopers
The ten numbered design-phase documents under docs/architecture now open with a banner saying they are a narrative frozen on 2026-06-13, and point to the current domain model and the ADR index instead.
#3562
· 2026-09-29
An act receipt names the command span its traffic carries
The receipt and the traffic finally share a name
fixednodedevelopers
receipt.commandSpanId is now present on act receipts and equals the _commandSpanId of the requests the act's verb started, so an act can be joined to its traffic in network_log. It was declared but absent on every act.
fixedmcpdevelopers
The act and credential fill tools return receipt.commandSpanId, and its description no longer says it is not yet delivered.
#3563
· 2026-09-29
Runtime messages, the API title and the MCP instructions write nightjar
The error names the product the way you type it
changedclidevelopersoperators
CLI output and errors that the CLI builds itself, such as the doctor report, surface probes and tunnel start-up errors, now write nightjar. Exit codes and error codes are unchanged.
changedcontroldevelopers
The OpenAPI document is now titled nightjar API, and error messages the node and control plane return, such as tunnel refusals and session id validation, write nightjar. Error codes are unchanged.
changedmcpdevelopers
The instructions the MCP server sends to a connecting client now open with nightjar hosted browser. No tool, argument or behaviour changes.
#3567
· 2026-09-29
The seeded CLI OAuth client is named nightjar CLI
A name on record, spelled as the repository
changedcontroloperators
Migration 0076 respells the seeded nightjar-cli OAuth client's display name from Nightjar CLI to nightjar CLI, so the operator's list-oauth-clients output matches the Bitspark naming rule.
#3570
· 2026-09-29
OAuth approval pages name the client that is actually asking
Only a vouched-for name heads the page
securitycontroloperatorsdevelopers
The consent, OOB copy and device approval pages used to say Claude Code for every OAuth client. They now name the client itself: a first-party client by its name, and a self-registered client as an UNVERIFIED application with its client id.
#3574
· 2026-09-29
Client registration refuses every invisible character in a name
What a name hides, registration refuses
securitycontroldevelopers
A dynamically registered OAuth client name is now refused if it contains any Unicode Default_Ignorable_Code_Point, such as variation selectors, tag characters or Hangul fillers, besides control, bidi and zero-width characters.
#3578
· 2026-09-29
The published API contract writes nightjar as its repository name
The contract spells its own name
docsdocsdevelopers
Descriptions in the published /v1 OpenAPI document now write the project name as nightjar, matching its repository. Only prose changed: no schema, field, header or operation id moved, and X-Nightjar headers keep their names.
#3579
· 2026-09-29
List the sessions one identity holds, in one call
Ask for one identity, not the whole org
addedcontroldevelopersoperators
GET /v1/sessions and GET /v1/sessions/page accept an identity filter, the identity's id. Combined with live, it lists the live sessions an identity's teardown must end, instead of listing every session in the org and filtering client-side.
addedsdkdevelopers
SessionFilter gains identity, sent by sessions.list and sessions.listPage; the mock client filters on it the same way.
#3582
· 2026-09-30
v2026.09.17.1
2026-09-17
The CLI's exit codes were documented nowhere
One means the floor gave way
docsclioperatorsdevelopers
A script author asking what nightjar returns on failure had nowhere to look: CLI_REFERENCE.md is generated and has no exit-code section, so the contract lived only in main.rs. Now stated in command-architecture.md.
#3438
· 2026-09-04
AGENTS.md drops 26 percent, and a silent clobber hazard goes with it
Nothing of ours inside a managed region
fixeddocsdevelopers
2,654 lines sat inside markers declaring them installer-managed, but 97 percent existed only here. An install would have destroyed about 1,900 lines of nightjar rules. That content moved out; AGENTS.md drops 169k to 126k tokens.
#3452
· 2026-09-04
AGENTS.md gets 58 sub-headings: 593 lines per heading becomes 99
An unbroken slab, given section lines
changeddocsdevelopers
The Git workflow section was 6,976 lines with ZERO sub-headings, so the file's own advice, enumerate the headings, could not work on the file. 58 headings added at real topic boundaries. Provably zero content change.
#3455
· 2026-09-04
Five MCP tool descriptions were being truncated at 2048 characters, silently
The tail never left the building
internalmcpdevelopers
A tool description over 2048 chars is cut by the client and the tail reaches no agent, with no error anywhere. Five of 39 exceed it. A guard now freezes those five as debt and blocks any new one.
#3456
· 2026-09-04
The external-state register now probes itself on a schedule
A cron is the only trigger it has
addeddocsdevelopersoperators
Eleven register rows are now probed every six hours and written to a generated file. The register's subject changes without a commit, so no merge gate could ever have seen it drift.
addeddocsdevelopers
Every probe carries a control whose expected answer is the opposite of the real probe's, and a failed control marks that row VOID rather than letting it read as a value.
#3460
· 2026-09-04
The deploy now says when the production edge is frozen
The rate limiter cannot deploy itself
internaldeployoperators
Every Caddyfile apply has refused since 2026-06-29 because the remote Caddy lacks the rate-limit module, and no surface reported it. deploy.sh now runs a read-only edge check after a deploy, and verify-edge.sh runs alone.
#3461
· 2026-09-04
Rust doc comments now build in CI, and 52 broken references surfaced
A reference that resolves, and one that does not
internaldocsdevelopers
About 2 MB of Rust doc-comment prose shipped without cargo doc ever running in CI, so no cross-reference in it had been checked. The first build found 97 unresolved intra-doc links. An advisory job now builds the docs and classifies them.
#3462
· 2026-09-04
Every ADR now shows what references it, generated rather than remembered
Every edge now points both ways
addeddocsdevelopers
ADRs carry a generated Referenced by block, drift-gated in CI. ADR-018 said it supersedes ADR-002 and ADR-006; neither of them carried a single reference back, in the direction a reader travels.
docsdocsdevelopers
Three networking relations are now declared rather than implied, so they render as labelled backlinks: ADR-018 supersedes, ADR-021 extends, ADR-035 reframes.
#3463
· 2026-09-04
daemon up stops guessing the control URL from a port number
The deployment says where it is
addedclioperatorsdevelopers
The CLI derived the daemon control-channel URL by adding one to the API port. That cannot work against a hosted deployment, so it asks the server instead, at a new public endpoint.
#3464
· 2026-09-04
The ADR backlink gate was running on files it never opened
The frame was smaller than the picture
fixeddocsdevelopers
The CI filter already fired on ui, core and deploy markdown, so the gate ran and reported zero drift about files its graph did not read. It now scans the same roots as its sibling link checker.
fixeddocsdevelopers
A generated backlink stated its relation in the referrer's voice, so a superseded ADR was labelled as the one doing the superseding. The label now inverts for the target.
#3465
· 2026-09-04
The credentials guide now says a login hop needs the auth host declared
The second gate was never on the map
docsdocsoperatorsdevelopers
The guide described the cloak gate only at session start (the url must be a declared advisor origin). It now says the same gate narrows every request, so a login hop to an identity-provider host fails unless that host is declared too.
#3468
· 2026-09-05
The credentials guide: what a lease keeps, and a capture never auto-promotes
The clock on the tab is not the clock on the lease
docsdocsoperatorsdevelopers
An identity lease keeps the session and the lease, not the tab: the node closes an idle session's browser 30 minutes after its last session verb; lease renewals do not count. A captured auth-state version is never promoted automatically.
#3475
· 2026-09-06
Choose a browser when starting a session
A browser choice at the start
addedconsoleoperatorsdevelopers
Choose Chrome or Cloak in the New session dialog. Cloak shows organization availability and requires a valid start URL; Chrome remains usable if availability cannot be checked.
The New session dialog now includes a Browser selector above Start URL, with Cloak availability and URL guidance.
#3478
· 2026-09-06
Unify session control and make authority visible
One operator, one controller
changedcontroloperatorsdevelopers
Human org admins can take over sessions and identity leases using their membership authority. API keys keep their own scopes, modes, and identity grants.
fixedsdkdevelopers
A successfully adopted controller is carried on subsequent calls for that session, including navigation and remote input. Tokens stay in client memory and are cleared on release.
changedconsoleoperators
Take control establishes one lease for navigation and remote input. Key creation shows execution mode and offers explicit workflow presets.
The key creation dialog now explains execution mode and offers explicit start-and-drive and remote SDK presets.
#3479
· 2026-09-06
Say which identity open mode is actually enforced
A stored setting is not a shipped behaviour
docsdocsdevelopers
The credentials guide (both twins) now says only exclusive is enforced at session-open: fork and readonly are stored and echoed read-side but not wired, and openModes echoes the stored default rather than reporting a capability.
#3483
· 2026-09-12
MCP identity discovery now says where provisioning and the spec live
The drive plane points at the provisioning plane
docsmcpdevelopers
identity_list_assumable and the server instructions now say provisioning (create identity, store credential, grant) is REST-only, name the routes and scope, point at the OpenAPI spec, and flag that openModes is an echo, not a capability.
docssdkdevelopers
The IdentityCreate defaultOpenMode description in the v1 OpenAPI spec now says only exclusive is enforced at session-open; fork and readonly are stored and echoed but not yet wired.
#3484
· 2026-09-12
Open modes other than exclusive are not planned, and the record says so
One session per identity; multiplex on your side
docsdocsdevelopers
The credentials guide twins, ADR-011, ADR-009 and open-questions Q24 now record the 2026-09-12 decision: only exclusive is enforced, fork and readonly are not planned, and consumers multiplex their actors onto one session per identity.
#3485
· 2026-09-12
The spec and MCP prose now say fork and readonly are not planned
Stored, inert, and honestly labelled
docssdkdevelopers
The OpenMode, Identity.defaultOpenMode, IdentityCreate.defaultOpenMode and AssumableIdentity.openModes descriptions in the v1 spec now say only exclusive is enforced by decision, and that fork and readonly are stored, inert and not planned.
docsmcpdevelopers
identity_list_assumable now says only exclusive is enforced by design (one live session per identity; multiplex your actors onto it) instead of today, so no reader plans around a mode that is not coming.
#3486
· 2026-09-12
The identity form stops promising open modes that are not coming
Exclusive, by design
changedconsoleoperators
The New identity form's open-mode hint now says fork and read-only are not planned and exclusive is the only mode, by design, instead of not enforced yet: one live session per identity, actors multiplexed onto it by the consumer.
The Default open mode field in the New identity form: the hint no longer says fork and read-only aren't enforced yet; it says they are not planned, and exclusive is the only mode by design.
#3487
· 2026-09-12
v2026.09.04.1
2026-09-04
warmResume now names the v1-only producer half it depends on
Consume, never mint
docsmcpdevelopers
The MCP surface lets a caller consume an auth-state version and mint none: capture is v1-only by design and promote was deferred. The description now says so, rather than pointing an MCP caller at a tool absent from their surface.
#3399
· 2026-08-31
A deep link into the console now survives signing in
Back where you were going
fixedconsoleoperators
Following a console link while signed out, such as one that opens the new key form, now brings you back to that page after you sign in, instead of to the start page.
The API keys page with the new key form open and its name filled in: where a signed-out visitor following a new key link now lands after signing in. Captured from a local build.
#3411
· 2026-09-02
Three documents promised a redaction floor that was removed 27 days earlier
A guarantee outlived its code
docsdocsdevelopers
The result contract and the getting-started guide told integrators every model-exit read is secret-shape-floored. That floor was removed 2026-08-07; floor_secret_shapes is now the identity function. Both now say so.
#3417
· 2026-09-03
Repair stale doc references and guard the ADR index against silent decay
An index that cannot lose a row
fixeddocsdevelopersoperators
The ADR index listed 31 of 56 ADRs and was diverging. All 56 now have a row, and a new guard fails when an ADR has none or a row names a missing file. Five dangling wiki-links, six dead path claims and one broken anchor are also fixed.
#3418
· 2026-09-03
The glossary had the two authority planes backwards
Two planes, never crossing
fixeddocsdevelopersoperators
The published glossary described both authority planes as credential mechanisms, and claimed captured network logs are filtered for secret values. Neither was true.
#3419
· 2026-09-03
The docs now say what we publish, and the register says it correctly
Probe it, or do not state it
fixeddocsdevelopersoperators
The external-state register was falsified 57 minutes after its own last edit and stayed wrong for 16 days across six rows. It said two npm packages were broken and burned when both were fixed and healthy.
fixeddocsdevelopers
check-doc-links reported zero broken links over 173 files while the repo's only broken link sat in the 34 files its roots could not reach. Widened to 204 files; it then caught the link, which is also fixed.
fixeddocsdevelopersoperators
Two ratified ADRs carried self-expiry clauses that fired on the npm publication and were never pulled. ADR-024 still said the packages were not published while they sat at 0.1.5 and 0.1.3.
addeddocsdevelopers
The root README now names the four doors a consumer can attach to, the ADR index lists all 56 ADRs instead of 31, and the architecture index reaches the ten sibling directories it never mentioned.
fixeddocsdevelopers
The published getting-started page told consumers ADR-035 was awaiting ratification, two months after it was ratified. The unpublished in-repo twin had it right.
#3423
· 2026-09-03
Networking docs point forward, and intranetMode stops saying it does nothing
A stale doc gains a forward pointer
fixeddocsoperatorsdevelopers
The published intranetMode description said toggling it does not yet change session behavior. It has governed all private tunnel reach since v2026.06.28.1, so the contract told org admins the opposite of the truth for nine weeks.
docsdocsdevelopers
Networking docs now carry forward pointers. ADR-002 and ADR-006 named none of the three later ADRs that changed them, and the architecture index mentioned ADR-018, ADR-021 and ADR-035 zero times.
docsdocsdevelopers
The published guides said local reach has no CLI and was awaiting ratification. The tunnel command ships and the ADR was ratified on 2026-07-01; only the signed installer is unbuilt.
#3425
· 2026-09-03
The sign-in routes now pass through the rate limiter they were always meant to
Two doors, one gate
securitycontroloperators
The GitHub sign-in entry points were classified as rate-limited and never actually were: they sat one layer outside the limiter. They are inside it now, so repeated sign-in attempts from one address get a 429 like every other public route.
#3434
· 2026-09-03
The env-var reference named 35 of the 72 variables the runtime reads
Half the dials were unlabelled
docsdocsoperatorsdevelopers
core/docs/configuration.md calls itself the canonical reference for the environment variables the node, daemon and CLI read. It named 35; the runtime reads 72. The 37 missing ones are now documented with defaults read out of the code.
#3437
· 2026-09-03
v2026.08.31.1
2026-08-31
State that daemon:files reads file content and writes to local disk
Consent needs the whole truth
securitycontroloperatorsdevelopers
The daemon:files scope described itself as 'List and stat files' while also reading file content and writing files to the caller's local disk. Granters saw a read-only description for our broadest local-disk capability.
#3362
· 2026-08-28
Stop enumerating act verbs in prose: the spec points at the enum
Read the enum, not a sentence
docscontroldevelopers
The published ActVerb description listed eleven verbs while the enum carried thirteen, so a client reading the spec could not discover fill or select. It now points at the enum instead of restating it.
#3370
· 2026-08-29
Correct the contract: inline clipboard capture is refused, not available
Say what the surface does
fixedcontroldevelopers
The OpenAPI contract described inline clipboard capture as a usable return mode and its result field as sometimes populated. Both are refused with a 400, so the descriptions now say so.
#3372
· 2026-08-29
Agents can prepare a config change for a human to approve
Compute the change, keep the click
addedcontroldevelopers
A new request kind lets an agent compute a config change, render its diff and file it for ratification. Preparing grants nothing: the record is inert until someone with the authority acts on it.
#3380
· 2026-08-29
The controller token comes back on a different header than it arrives on
Correct, precise, and pointing away from the fix
fixedcontroldevelopers
Adopt mints the controller token onto a RESPONSE header; renew and release expect it back on a DIFFERENT REQUEST header. Renew never named it and neither declared it. All three endpoints now declare their required headers.
#3383
· 2026-08-30
An unknown config change class is now refused when it is filed
Refuse at the door, not at the desk
changedcontroldevelopers
POST /v1/config-change-requests now accepts only declared change classes. Filing an unrecognised target returns 400 and names the classes that are allowed, instead of queueing a request that no one could ever apply.
#3386
· 2026-08-30
App authors get a security guide for what is enforced and what is not yet
A real floor, and an open gate
docsdocsdevelopers
A new guide tells app authors what App Surface protects today and what is only decided. The headline: there is no consent gate or scope check on import, so reachability to the node is the authorization.
#3387
· 2026-08-30
A refusal that was correct now also names the lease you can actually renew
Name the road you are not on
fixedcontroldevelopers
Renewing the identity lease on a controller-owned session answered 'session is not identity-bearing' and stopped. True, and it reads as 'no renewal exists'. It now names the CONTROLLER lease and its renew verb.
#3388
· 2026-08-30
The SSRF denial now names declared hosts, except where that would be a bypass
Name the door, not the wall
fixednodeoperatorsdevelopers
Direct egress blocked by the SSRF guard said only 'private address'. True, and it left the caller nothing to act on. It now names intranet_mode and the declared-hosts allowlist for the classes where that is the sanctioned path.
#3390
· 2026-08-30
The reachability refusal now names the right remedy of two, not a guess
Two gates, two doors
fixednodeoperatorsdevelopers
One error variant covered two different gates with two different remedies, so a refusal could not name a correct next step for either. It now carries which gate refused and names that gate's remedy.
#3392
· 2026-08-30
v2026.08.28.1
2026-08-28
Console dialogs converge on the nightglass modal size scale
One scale of night for every window
changedconsoleoperatorsdevelopers
Console dialogs now use the adopted design system's three-step size scale and its dialog chrome: a header band with an explicit close button; widths converge on sm/md/lg.
The Create API key dialog: free-form 56rem tightens to the adopted lg width (48rem), and dialogs gain the upstream chrome - a header band with a close button.
#3349
· 2026-08-27
v2026.08.25.1
2026-08-25
The public marketing site finally has a deploy pipeline
Merged is not deployed
addeddeployoperators
A website merge used to trigger the console deploy, ship nothing of the site and report green. A dedicated workflow now runs the sanctioned script and asserts the live stamp, and the console filter no longer matches the website.
#3301
· 2026-08-23
Agents can read their own scopes with the new whoami tool
Know what you hold
addedmcpdevelopersoperators
The MCP surface now exposes whoami, which returns the calling credential's own orgId, agentId, keyId and scopes.
#3311
· 2026-08-25
The generated MCP reference now carries the ADR-022 D9 cross-surface matrix
A number that cannot hide its own caveat
addeddocsdevelopers
The generated tool-surface reference now reports capability coverage across http, mcp, cli and sdk, with the tools it cannot represent counted beside it.
#3314
· 2026-08-25
The cross-surface matrix now cites the ruling that governs a surface's scope
A number a reader can interpret
fixeddocsdevelopers
Where a surface declares a scope ruling, the matrix now cites it beside the coverage figure, so a non-exposed state is not misread as debt.
#3316
· 2026-08-25
D9's two unbuilt artifacts are now recorded as deferred, not left as open gaps
A decision reads differently from a gap
addeddocsdevelopers
The generated reference now records D9's per-capability sheets and effects/safety view as deliberately deferred, each with the condition that would revisit it.
#3319
· 2026-08-25
v2026.08.23.2
2026-08-23
Correct the crypto-delete scope shown in console settings
Say which keys, and mean it
fixedconsoleoperators
The governance panel described crypto-delete as destroying per-session keys. It destroys per-org and per-credential keys.
The crypto-delete row now names the org and credential scopes instead of a session scope.
#3291
· 2026-08-23
Name the control-plane authority for artifact collection, not the node's
Name the scope the caller can actually hold
fixedmcpdevelopers
The tool surface named profile-maintenance and runtime-admin as the authority for artifact collection. Those are node-side arms with no control-plane analogue, so an agent looking up the scope it needs found names that do not exist there.
#3294
· 2026-08-23
Access-request keys no longer mint with raw drive
One default, every door
securitycontroloperatorsdevelopers
A key minted by approving an access request took the database default and granted raw drive. It now binds the same delegation_required default as every other mint path.
#3296
· 2026-08-23
v2026.08.22.2
2026-08-22
Agent keys minted from the self reach template can be rotated again
The exception that stopped at the door
fixedcontroloperators
An org that opted into agent self reach could mint a reach:self key but never rotate it, because rotation demanded a scope the template exists precisely not to require.
#3249
· 2026-08-22
New API keys default to requiring delegation, not raw session driving
A default withholds, never grants
securitycontroloperatorsdevelopers
A key minted without an explicit mode now gets delegation_required instead of direct, so it cannot drive a session by its own raw presentation. Existing keys are untouched and keep the mode they were minted with.
#3273
· 2026-08-22
v2026.08.22.1
2026-08-22
A malformed declared host is now refused instead of silently dropped
A rule you declared should never become no rule
fixedcontroloperators
Declaring a reachable host that cannot be parsed used to be accepted and then discarded. If it was the only entry the allowlist became empty, and an empty allowlist is permissive, so the one rule you declared quietly became no rule at all.
#3227
· 2026-08-21
Show denied advisor origins where the declared set is edited
The evidence belongs beside the editor
addedcontroloperatorsdevelopers
A new org-scoped endpoint reports which advisor origins your sessions were refused, so the person editing the declared set can see what is missing.
#3235
· 2026-08-21
A scheme-less advisor origin is now refused instead of silently coerced
A scheme is not optional
changedcontroloperatorsdevelopers
Declaring an advisor origin without a scheme now returns 400 instead of being stored as http://HOST — a form that could never match an https advisor session, because the comparison is exact on scheme and port.
#3245
· 2026-08-21
A 403 scope denial now names which key was refused
A refusal that says who asked
addedcontroloperators
Server-side traces for a refused request now carry the acting key id, so a 403 can be joined to the caller rather than only to the scope and the request.
#3246
· 2026-08-21
Correct the website README: a merge here deploys nothing at all
A green run can mean nothing happened
fixeddocsdevelopers
Both app READMEs claimed a console deploy happens automatically. No deploy secret exists, so that workflow gates every real step behind an arming check and goes green having done nothing. Neither app has a live auto-deploy.
#3248
· 2026-08-21
The scratchpad identity check can return a peer's handle on a resumed session
A path cannot tell you whose it is
docsdocsdevelopersoperators
AGENTS.md said a session-UUID scratchpad path carries your own handle. On a resumed session it need not track the running session at all, so the first 8 characters can name a live registered peer instead of you.
#3252
· 2026-08-22
Show recently-denied advisor origins beside the field that declares them
The evidence sits beside the control
addedconsoleoperators
The governance tab now lists advisor origins that were recently denied, directly under the field that declares them.
#3256
· 2026-08-22
Say why there is no verb to release your own artifacts
A missing verb, explained
docsmcpdevelopers
The download-to-artifact tool now explains why an agent cannot reclaim its own artifacts, instead of only stating that it cannot.
#3258
· 2026-08-22
Cloak session start now honours a wildcard advisor origin declaration
One rule, one implementation
fixedcontroloperatorsdevelopers
A wildcard advisor origin was honoured when the browser fetched a page but refused when the session started, so half the declaration worked and nothing said which half.
#3261
· 2026-08-22
Correct the last false launch-state claim in the docs and website plan
Measure the claim before you plan around it
changeddocsdevelopers
The planning draft said concepts had no public glossary. One is deployed and defines all five concepts the clause named, so the claim is struck in place.
#3262
· 2026-08-22
v2026.08.21.6
2026-08-22
Advisor origins accept a wildcard, so a CDN change no longer breaks cloak
One entry, every subdomain
fixednodeoperators
A declared advisor origin can now use a leading wildcard label and will match any subdomain. Previously only an exact host matched, so a provider that generates hostnames could break a cloak session with no config change on your side.
#3205
· 2026-08-21
A drained session now closes with its own code, distinct from a plain end
A redeploy is not a refusal
addednodedevelopers
The session-ended journal event now carries a typed cause beside its human reason, and a session drained by a redeploy closes the events socket with 1012 instead of 4410.
#3213
· 2026-08-21
Add nightjar mcp install to wire a repo to a saved login
The repo names the login, never the key
addedclidevelopersoperators
nightjar mcp install points a repo's .mcp.json at a saved login, and replaces an older entry that carried an Authorization header in the same write.
#3215
· 2026-08-21
Tell docs authors that merging does not deploy the docs site
Merged is not deployed
docsdocsdevelopers
The docs app now carries a README saying a merge to main does not reach the live docs site, and how to verify a change actually shipped.
#3231
· 2026-08-21
Warn that a website merge deploys the console and ships nothing
Green, and the wrong app
docsdocsdevelopers
The public website app now carries a README saying a merge there triggers the console deploy, goes green, and ships none of the site.
#3240
· 2026-08-21
v2026.08.21.5
2026-08-21
Move rationale out of the API spec and into the concept pages
Contract at the call site, reasons on the page
docsdocsdevelopers
Thirty-two OpenAPI descriptions shed their rationale paragraphs, which now live verbatim on two concept pages. Each field keeps a one-line pointer.
#3150
· 2026-08-21
Declare a changelog position or the contract job now fails
A position declared beats a position inferred
changeddocsdevelopers
The changelog contract job now fails a PR that declares no position at all — neither an entry nor the changelog:none label.
#3151
· 2026-08-21
act upload now says what SUCCESS does and does not mean
Set is not attached
docsmcpdevelopers
act upload issues CDP SetFileInputFiles, so it cannot observe whether the page accepted the file - but the description never said so, and consumers read SUCCESS as attachment. It now states the limit and names the discriminating field.
#3153
· 2026-08-21
act upload's receipt names what it SET on the input, not what the page attached
Set, not attached
docsmcpdevelopers
The uploadedRefs receipt said the refs were ATTACHED. They are the refs the verb resolved and set on the file input, before the page is handed anything - so a page-side upload failure is invisible to the caller.
#3156
· 2026-08-21
Make the how-it-works page's Where to go next section actually link
A named destination should be a door
fixeddocsdevelopersoperators
The concept page's closing section named three destinations in bold prose with no links. All three are now links, and each target route was verified to exist.
#3158
· 2026-08-21
Group the harvested spec rationale by the kind of mistake it prevents
Sort by the shape of the error, not the shape of the thing
changeddocsdevelopersoperators
The rationale moved out of the spec is now grouped by what it protects you from, and sits before each page's closing section rather than after it.
#3160
· 2026-08-21
Approving an access request for reach:self no longer 403s the operator
A gate no human could pass, on the surface built for exactly this
fixedcontroloperatorsdevelopers
An agent could file an access request for reach:self and no human could ever approve it. The approve gate checked the scope against the approver's own ceiling, and reach:self appears in no human role, so the click always failed.
#3165
· 2026-08-21
A blank org header no longer dead-ends a multi-org operator
One definition of no org selected, not two that agree by luck
fixedcontroloperators
On the OAuth sign-in leg, a present-but-empty X-Nightjar-Org header made a multi-org operator see an error telling them to set that same header, instead of the org picker.
#3167
· 2026-08-21
Pin the scan budget clock seam, and record the bound itself as untested
An untested bound, honestly named
internalcontroldevelopers
The provenance scan's time budget now reads a runtime clock at its three enforcement sites, with a test pinning that production behaviour is unchanged. The bound itself remains untested, and the reason is recorded in the source.
#3186
· 2026-08-21
Pin the egress-cap env shape production actually passes, not the unset one
The flag decides, not the default
internalnodedevelopers
The default-off test used remove_var, pinning the unset case. Deployment passes an empty string, which nothing pinned. Adds that arm, and fixes a lock that let the two tests race.
#3189
· 2026-08-21
Declaring an advisor origin also bounds the hosts its page fetches
One origin, many hosts
docscontroloperatorsdevelopers
The declaredAdvisorOrigins description now states that the set bounds subresources, not just navigation, and that host matching is exact with no wildcards.
#3193
· 2026-08-21
Every concept page now links back to the API reference
A pointer that only goes one way is half a link
addeddocsdevelopersoperators
The spec's doc comments point at the concept pages, but no concept page pointed back. All four now link to the API reference, in prose that already named it.
#3195
· 2026-08-21
CI now fails when a writable governance setting has no console control
A setting nobody can reach is a setting nobody can fix
internalcontroldevelopersoperators
A governance field that can be changed by API but has no control in the console now reds CI, unless it is exempted with a written reason.
#3197
· 2026-08-21
Declared advisor origins can now be edited in the console
The last field with no control
addedconsoleoperators
Data governance gains an editor for declared advisor origins, the field that previously had no console control at all.
#3204
· 2026-08-21
v2026.08.21.4
2026-08-21
A direct-path SSRF denial now leaves a per-session audit record
Both routes write it down
securitynodeoperators
An SSRF denial on the direct egress route bumped its counters but emitted no EgressAuditEvent, so the same security event the tunnel-floor deny journals was invisible per-session on that route. It now emits one.
#3143
· 2026-08-21
v2026.08.21.3
2026-08-21
A session ended by a redeploy now says so, instead of later looking abandoned
Say why the session ended
fixednodedevelopersoperators
A session closed by a node redeploy recorded nothing at the time, and was later reported as abandoned - which says the client went stale when the host had actually restarted.
#3119
· 2026-08-21
Two explanation pages: what Nightjar refuses, and what things are not
Explain the no, not only the yes
addeddocsdevelopersoperators
The docs site gains two explanation pages: the deliberate refusals and the reasoning behind them, and the category corrections where a name suggests one thing and the system means another.
#3124
· 2026-08-21
Browser sessions can no longer reach link-local addresses on the direct route
Every route through the same gate
securitynodeoperatorsdevelopers
Sessions using split or platform egress were launched without a proxy, so their direct traffic reached the cloud metadata address unscreened. They now run through the same chokepoint every other route uses.
#3125
· 2026-08-21
Published API descriptions no longer open with an internal issue number
The first words belong to the reader
fixedsdkdevelopers
Nineteen schema descriptions in the published spec began with an internal issue number. The number moved into a source-only comment; the description now opens with what it describes.
#3126
· 2026-08-21
Serialize the CLI test that reached a process-global through production dispatch
A lock excludes only those who take it
internalclidevelopers
A test reached the process-global diagnostics context through a production dispatch without taking the test lock, racing the tests that did.
#3129
· 2026-08-21
Add the two boundary pages to the docs sidebar
A page nobody can find is a page nobody reads
changeddocsdevelopersoperators
The How Nightjar works section now lists What Nightjar refuses and What these things are not, between How it works and the Glossary.
#3130
· 2026-08-21
The SDK drift record is regenerated and CI now fails when it goes stale
The record that shows drift had drifted
internalsdkdevelopers
SDK-versus-spec coverage is now a machine-checked number instead of a snapshot someone remembered to re-run.
#3133
· 2026-08-21
v2026.08.21.2
2026-08-21
A redeploy now finishes draining browser sessions instead of being killed
Finish the drain before the door closes
fixeddeployoperators
The node's shutdown drain gave up after 8 seconds even though the container allows 60, so a redeploy killed sessions it had time to close cleanly.
#3097
· 2026-08-21
Cite code by symbol, not by line number, in the credential guides
A citation that survives the code moving
fixeddocsdevelopers
Code citations in the credential guides now name a module and symbol instead of a file and line, so they stay true when the file changes.
#3103
· 2026-08-21
Every code citation in the credential security guide now resolves
Pointers that all land somewhere real
fixeddocsdevelopers
The credential security guide no longer cites code by file and line. All 35 pointers are now module and symbol names, checked against the source tree on every CI run.
#3104
· 2026-08-21
Explain how Nightjar works, with figures, under its own nav label
The label finally cashes its cheque
addeddocsdevelopersoperators
The 'How Nightjar works' section now contains an explanation, not just a glossary.
#3118
· 2026-08-21
Choose your organization when signing in with more than one
The sign-in page finally asks which organization you mean
addedcontroloperators
Signing in to an application while your account belongs to several organizations now shows a page asking which one to use, instead of an error naming a header a browser cannot set.
#3120
· 2026-08-21
v2026.08.21.1
2026-08-21
Correct why the Run targetId field is always null
A reason can expire before the fact does
fixedcontroldevelopers
The API reference said targets do not exist yet. They do - a run simply cannot be bound to one.
#3063
· 2026-08-20
Say why three API fields are always empty
An empty field can still say why
docscontroldevelopers
Three fields the API returns are never populated. The reference now says so, and says why.
#3067
· 2026-08-20
Clearer sign-in message when your account belongs to several organizations
Two organizations, one sign-in, no way to choose
fixedcontroloperators
The multi-organization sign-in page no longer tells you to run an approval from the CLI. That step does not exist on this flow, so the message now says plainly what happened and what will actually work.
#3069
· 2026-08-20
Two more ways a clean-looking issue turns out to have nothing to build
Reading the artifact is the check
docsdocsdevelopers
The dedup guidance listed two ways an issue can pass every structural check and still not be takeable. Four screens in one day found four reasons, and two of them were new.
#3072
· 2026-08-20
Give the node time to finish draining browser sessions on redeploy
Let it finish before you pull the plug
fixeddeployoperators
The node now gets 60 seconds to drain its browser sessions on redeploy, instead of the 10-second default that killed the drain part-way through.
#3075
· 2026-08-20
A seat records when its own failure mode fires hardest
Urgency is when a guess travels furthest
internaldocsdevelopers
The SW6 seat keeps a list of times it measured something correctly and published it wrongly. Two more were added, along with the condition under which it happens.
#3076
· 2026-08-20
api-types now ships spec provenance, so drift checks can answer for it
A fingerprint must cover every source
addedsdkdevelopers
api-types is generated from the OpenAPI document and the WS event schemas but shipped no record of which revisions it came from. It now stamps both, so the release check can say a bump is due instead of reporting NOT APPLICABLE.
#3077
· 2026-08-20
The documentation is reachable from the marketing site
A door nobody can find is a wall
addeddocsoperatorsdevelopers
The marketing site carried no link to the documentation at all. It now closes with one, so the explanation layer is reachable from the front door.
changeddocsoperatorsdevelopers
The docs sidebar group Concepts is now How Nightjar works, at the same rank, so it reads as an argument rather than a cabinet of terms.
#3081
· 2026-08-20
Console screens can point at the explanation for what is on them
Answer the question where the question is asked
addedconsoleoperatorsdevelopers
Reach grants and Identities now carry a contextual link into the docs, naming the question the screen raises rather than sending you to a docs front page to search.
The PageHeader showcase. After adds a third example carrying a contextual docs link, and documents the two new props. Captured from a pristine build and this branch, both asserted to have the component's styles applied.
#3083
· 2026-08-20
A docs guide can no longer claim a tool count the manifest disagrees with
A count must come from the thing it counts
addeddocsdevelopersoperators
The credentials guide said the MCP surface was a closed set of exactly 9 tools. It is 38. Both numbers now render from one validated selection, and CI refuses a tool table that has drifted from it.
#3089
· 2026-08-20
v2026.08.20.12
2026-08-20
Document the four Run fields that are always null
Say what the empty fields mean
docscontroldevelopers
The API reference now says which Run fields are always null today, why, and what would change that.
#3060
· 2026-08-20
v2026.08.20.11
2026-08-20
Pin the NULL-profile filter in the reclaim report so removing it turns CI red
A comment is not a signal
internalcontroldevelopers
The reclaim report reads a nullable column into a non-Option String and is safe only because its query filters the NULLs out. That filter now has a regression test instead of a comment.
#3057
· 2026-08-20
v2026.08.20.10
2026-08-20
A CI watcher settled while two required checks did not yet exist
Absent is not incomplete
docsdocsdevelopersoperators
AGENTS.md prescribed a count floor for merge watchers. A job whose dependencies have not resolved is never created, so it cannot be incomplete, and the floor passes straight over it.
#3051
· 2026-08-20
A session with no profile no longer fails the reads that scan it
One bad row should not sink the org
fixedcontroldevelopersoperators
Provenance and session-replay reads now tolerate a session whose profile column is null, instead of failing the whole request.
#3054
· 2026-08-20
v2026.08.20.9
2026-08-20
Provenance answers now say how far the scan looked
An empty answer should say why
addedcontroldevelopers
Every scan-backed provenance response reports how many sessions it read, the cap, and which bound ended the scan.
addedsdkdevelopers
ScanExtent and ScanCompletion are exported so a client can branch on why a scan stopped.
#3033
· 2026-08-20
Record the cross-suite test collision that no single file can reveal
Your green is someone else's red
docsdocsdevelopers
AGENTS.md now records the collision class where a new test suite breaks a neighbour's global-count assertion, and why seeding-side fixes relocate the problem rather than removing it.
#3040
· 2026-08-20
The identity check in AGENTS.md passed on another agent's handle
Resolving is not owning
docsdocsdevelopersoperators
AGENTS.md told you to verify your own address with a bb send --dry-run. That proves a handle exists, never that it is yours, so the check returned a clean pass on a peer's identity.
#3043
· 2026-08-20
v2026.08.20.7
2026-08-20
Report what a profile-store reclaim would remove, removing nothing
Count it before you cut it
addedcontroloperatorsdevelopers
An opt-in control worker logs what a profile-store reclaim would remove, reconciling the node's directory list against session records. It deletes nothing, and cannot: this build has no delete capability at all.
#3031
· 2026-08-20
v2026.08.20.6
2026-08-20
Redeploy drains browser sessions instead of stranding them
Let them out before the gate shuts
fixednodeoperators
The node now shuts down on SIGTERM, and drains live browser sessions before stopping — under a time budget, so it exits cleanly inside the container grace period.
#3030
· 2026-08-20
v2026.08.20.5
2026-08-20
Ask the provenance oracle about many hashes in one request
Many questions, one pass
addedcontroldevelopers
POST /v1/artifacts/provenance takes a list of content hashes and answers one entry per hash. A hash nothing produced comes back as an entry with an empty set, never a 404, so absence stays a usable answer.
#3026
· 2026-08-20
v2026.08.20.4
2026-08-20
Pin the act response wire shape in an end-to-end guard
Pin the shape, catch the drift
internalcontroldevelopers
The workspace jail end-to-end suite now pins the shape of the act success and refusal envelopes against committed fixtures, so an unannounced field addition or removal fails CI instead of shipping silently.
#3019
· 2026-08-20
Provenance now records what the node did to an artifact's bytes
Two axes, not one
addedcontroldevelopers
Artifact provenance gains an optional processing field: raw, derived or unknown. Read it together with direction.
#3021
· 2026-08-20
v2026.08.20.3
2026-08-20
Command-scoped provenance: one call for what a command touched
Ask the command what it touched
addedcontroldevelopers
A new v1 route resolves a command span id to its occurrences: the verb, the outcome, and the artifacts it touched.
addedsdkdevelopers
The SDK gains commands.provenance, mirroring the existing artifacts.provenance.
#3020
· 2026-08-20
v2026.08.20.2
2026-08-20
Agents can find a page region by the hash of its content
The hash is the address
addedmcpdevelopers
A new projection_search tool asks which subtree projects to a given sha256 — the inverse of the projection-hash check that wait and act already carry.
#3013
· 2026-08-20
v2026.08.20.1
2026-08-20
Superseded auth-state versions now follow your org's retention window
History fades, the head remains
addedcontroloperatorsdevelopers
Captured auth-state versions older than your organisation's retention preset are now reclaimed. The active version is never removed, nor is one a live session could still resume from.
#3008
· 2026-08-19
v2026.08.19.12
2026-08-20
Tool descriptions no longer say no artifact collector exists
A warning outlived the fact it rested on
fixedmcpdevelopersoperators
The artifact tool descriptions told every agent that no hosted surface exposed a collector. That stopped being true when POST /v1/artifacts/collect shipped, so the text now names the endpoint and the authority it needs.
#3007
· 2026-08-19
v2026.08.19.11
2026-08-20
Find a region by the hash of its content, over the v1 API
A verb earns its own gate
addedcontroldevelopers
The v1 API can now ask which subtree projects to a given sha256 — the inverse of the projection-hash check that wait and act already carry.
#2999
· 2026-08-19
v2026.08.19.10
2026-08-20
The act result's delta is now a declared shape, not an untyped blob
Declare what the wire already carries
fixedmcpdevelopers
act and credential_fill declared their delta with no type at all. The wire carried 28 fields and 6 closed enums that no generated client could see.
#2998
· 2026-08-19
v2026.08.19.9
2026-08-20
Reclaim expired controller idempotency records after a grace period
The tombstone still speaks
addedcontroloperators
The controller idempotency table now has a reaper. It was the fourth ticket store and nothing had ever deleted from it.
changedcontroldevelopers
An Idempotency-Key reused long after its retention horizon now re-executes instead of returning an expired error. Well before that, the error is unchanged.
#2990
· 2026-08-19
v2026.08.19.8
2026-08-19
A fully swept run no longer reports itself as active forever
A mark that outlives its evidence
fixedcontroloperatorsdevelopers
Run status is computed on read, and its "this run never had activity" test asked whether the sessions and connections tables were empty. Once retention reclaimed those rows the test passed again, so a finished run looked new.
#2991
· 2026-08-19
v2026.08.19.7
2026-08-19
You can now collect a profile's unreachable artifacts through the API
Expose what exists, at the authority it declares
addedcontroloperators
POST /v1/artifacts/collect runs the node's reachability-based artifact sweep for one profile and returns what it collected.
#2979
· 2026-08-19
Make a chromiumoxide upgrade trip the workaround it could make removable
The upgrade is the reminder
internalnodedevelopers
A same-document navigation workaround is pinned to the chromiumoxide version it was reasoned against, so the next upgrade fails the build instead of quietly outliving its cause.
#2985
· 2026-08-19
Artifact provenance now reports which way the bytes flowed
One hash, two possible origins
addedcontroldevelopers
The provenance oracle now reports a direction for each artifact plus the command span that minted it. Direction is derived from a closed verb set and reports unknown rather than guessing when the verb cannot determine it.
#2992
· 2026-08-19
Locate a region by the hash of its content, not by a container that re-renders
One region, four depths
addednodedevelopers
The node can now answer which subtree projects to a given sha256, the inverse of the projection-hash check that wait and act already carry.
#2993
· 2026-08-19
v2026.08.19.6
2026-08-19
An upload now names the artifacts it attached
Echoed, not observed
addedcontroldevelopers
act with verb upload now returns the artifact refs it attached, on the receipt. Proving N files are attached no longer means finding N chips in a perception digest that is capped and gets denser as N grows.
#2980
· 2026-08-19
v2026.08.19.5
2026-08-19
Restore the reach namespace's lost documentation in the SDK
A comment must touch what it describes
fixedsdkdevelopers
The SDK reach namespace lost its docs when artifacts was inserted between the comment and the member it described. Hover and the published types showed nothing, including the note that claim is excluded on purpose.
#2976
· 2026-08-19
Describe what perceive actually returns in its MCP output schema
Declare the shape you send
fixedmcpdevelopers
The perceive output schema said its perception field was passed through verbatim. That is only true in full mode, and the default is compact.
addedmcpdevelopers
The 12 keys the renderer adds to perception are now declared and documented, so clients can read the shape they receive.
#2981
· 2026-08-19
v2026.08.19.4
2026-08-19
The provenance oracle now tells you its answer may be incomplete
Empty is not not-found
fixedcontroldevelopers
The provenance route's docs presented two causes of an empty answer as the complete set and called the ambiguity a security property. A third cause, the 500-session scan bound, is a completeness limit and now says so.
#2959
· 2026-08-19
The SDK can now ask which session produced an artifact
A hash is a question
addedsdkdevelopers
artifacts.provenance(hash) resolves a content hash to the sessions that produced it, with the verb, page and time.
#2965
· 2026-08-19
A reaped session's recording is finalized before its browser is torn down
Finalize first, then tear down
fixedcontroloperators
The transport reaper tore down a crashed session's browser without first asking the node for its recording, so an opted-in capture was left unsealed and unindexed - and therefore unreadable.
#2968
· 2026-08-19
Artifacts are not collected with the session, whatever our docs said
Say what is true, and say the negative out loud
fixedcontroldevelopersoperators
The download-to-artifact endpoint promised that artifacts are garbage-collected with the session. Nothing collects them at session end.
fixedmcpdevelopers
The download_to_artifact tool carried the same false guarantee. An agent read it, ended its session, and nothing was collected.
#2971
· 2026-08-19
Dead session capabilities are reclaimed instead of waiting for org deletion
A spent key is not a record
fixedcontroloperators
A revoked or expired session capability row had no release path at all: only deleting the organisation removed it.
#2972
· 2026-08-19
v2026.08.19.3
2026-08-19
Docs deprecate the env-var Bearer pattern, now that a saved login exists
A frozen copy is not a credential
deprecateddocsdevelopersoperators
Every MCP host recipe now leads with nightjar auth login. Carrying the key in an environment variable or header template is marked deprecated, with the incident that motivated it as the reason. No recipe is removed.
#2946
· 2026-08-19
OAuth tokens are reclaimed once their grant is revoked, not once they expire
The revoked row is the evidence
fixedcontroloperators
The retention sweep deletes oauth tokens past their expiry whose grant is already revoked. An expired token under a live grant is kept: revoke reads it with no expiry filter, so deleting it would make revocation a silent no-op.
#2955
· 2026-08-19
v2026.08.19.2
2026-08-19
Stop the recording gate's anti-vacuity control arm from flaking under load
One deadline cannot serve two opposite polarities
internalcontroldevelopers
One mock-node helper served two opposite expectations through a single timeout, so the deadline expiring was the PASS for four denial tests and the FAILURE for the arm that proves them non-vacuous.
#2949
· 2026-08-19
Terminal reach grants are listed for 90 days, then reclaimed
History has a stated length
changedcontroloperatorsdevelopers
A revoked or expired reach grant stays in the owner-scoped list for 90 days after it became terminal, and its row is then reclaimed.
#2951
· 2026-08-19
v2026.08.19.1
2026-08-19
Retention keeps every idempotency ticket a replay can still reach
Keep every ticket a replay can reach
fixedcontroldevelopersoperators
Retention keyed on session status, so it reclaimed idempotency tickets that the API would still serve replays for. It now keys on the handler's own reachability condition, and sweeps the fill-credential store too.
#2942
· 2026-08-19
v2026.08.18.10
2026-08-19
The egress-audit dedup set now belongs to its session instead of the process
Owned, so nothing is left to forget
fixednodeoperators
The egress-audit drain kept one dedup set for the whole node process, keyed by session and never pruned, so entries outlived the sessions that produced them.
#2933
· 2026-08-18
v2026.08.18.9
2026-08-19
nightjar auth login: a saved login, so no token ever sits in a repo file
The login names the destination, not the repo
addedclidevelopersoperators
'nightjar auth login NAME' signs you in by device flow and saves the credential to an owner-only local store under a name you choose. Nothing is typed at a prompt and no token is passed on a command line.
addedcontroldevelopers
The OAuth token response now names the binding it minted: the org and agent ids, plus their display names when the deployment has them. All value-free ids, never secret material.
#2914
· 2026-08-18
The crashed-session reaper now reaches sessions that never held an identity
A filter is not a definition
fixedcontroloperators
The reaper's candidate query joined identity leases, so a session that never assumed an identity could never be a candidate for reclamation.
#2928
· 2026-08-18
v2026.08.18.8
2026-08-18
Look up which session produced an artifact, by its content hash
Ask the hash who made it
addedcontroldevelopers
A new provenance read on the /v1 artifacts path answers which session minted an artifact, with which verb, against which page, and when.
#2895
· 2026-08-18
Reclaim stale MCP transport connection rows in the retention sweep
Nothing else drains this table
fixedcontroloperators
The retention sweep now deletes transport_connections rows that no live session can still be reaped through.
#2916
· 2026-08-18
v2026.08.18.7
2026-08-18
Whether a command needs the server is now declared, not defaulted
Absence of a declaration is not evidence of a value
internalclidevelopers
Every operation declares whether it needs the server; the CLI reads that instead of a denylist of one.
#2892
· 2026-08-18
v2026.08.18.6
2026-08-18
MCP handshakes are now queryable per API key, not only greppable in logs
Ask the platform, not the logs
addedcontroloperatorsdevelopers
Each MCP handshake now records its outcome per API key, so a connect-failure rate is one security-log query instead of a day of log forensics.
#2889
· 2026-08-18
v2026.08.18.5
2026-08-18
The console selector fields no longer claim CSS is the only form
One parser, eight forms, three surfaces
fixedconsoleoperatorsdevelopers
The Drive panel's selector inputs said "CSS selector", but the value is resolved with the full eight-form locator grammar — so seven forms were advertised as unavailable.
The session Drive panel's act selector: the placeholder now demonstrates both a bare CSS selector and a prefixed form, and the hint names all eight.
#2883
· 2026-08-18
The typed client can now ask for part of a session journal
Ask for the window, not the whole capture
addedsdkdevelopers
journal() and journalWithMeta() take an optional args object, so a caller can narrow a recorded journal by sequence cursor, time window, or verb instead of fetching all of it.
#2885
· 2026-08-18
The typed client can filter a session's console log and network capture
Take the slice, leave the document whole
addedsdkdevelopers
consoleLog() and networkHar() take an optional args object, so a caller can narrow by cursor, tab, level, URL, method or status range instead of refetching everything to poll.
#2887
· 2026-08-18
Identity lease transitions are now recorded as events
Write it down before it disappears
addedcontroloperatorsdevelopers
Taking, releasing, force-releasing and reaping an identity lease now each write an event.
#2888
· 2026-08-18
v2026.08.18.4
2026-08-18
Credential store errors now speak the auth surface's words
One word, one meaning
fixedclioperatorsdevelopers
Credential store errors now say credential rather than profile, which had three other meanings a reader could land on.
#2871
· 2026-08-18
An act receipt now names the span its network traffic is stamped with
Start from the act, not the journal
addednodedevelopers
ActReceipt now carries commandSpanId - the same key network_log entries publish as _commandSpanId - so a client can go from an act straight to the traffic it provoked.
#2882
· 2026-08-18
v2026.08.18.3
2026-08-18
Troubleshooting now states which field carries what, on each path
Match the code, not the message
addeddocsdevelopers
A troubleshooting section stating which error field rides which path, and where to read it.
fixedmcpdevelopers
Corrected a module header that described the MCP error result as carrying only a code and a message.
#2878
· 2026-08-18
Network log entries now name the act that was in flight when they started
Which requests did this act cause
addedcontroldevelopers
Each network_log entry can now carry _commandSpanId - the command span in flight when that request STARTED - so act-caused traffic is identifiable without matching timestamps.
#2881
· 2026-08-18
v2026.08.18.2
2026-08-18
Fetch a session's timeline for a time window, not just from a cursor
A cursor cannot name the ten minutes it went wrong
addedcontroldevelopers
The journal and session-activity reads take since and until, so you can ask for the window a session misbehaved in instead of paging from a cursor.
addedcontroldevelopers
Journal events now carry the tab they belong to, and the journal read takes a coarse verb filter.
#2874
· 2026-08-18
The v1 error contract now says which token the code field carries
Same name, different token
docscontroldevelopers
V1Error.code now documents that it carries the RENDER token, and which field the same token rides on the other paths that emit a Nightjar error.
#2875
· 2026-08-18
CLI help now describes the full locator grammar it accepts
Say what the flag really takes
fixedclioperatorsdevelopers
Sixteen selector flags said CSS selector while accepting eight locator forms; four that really are CSS-only were left alone.
#2879
· 2026-08-18
v2026.08.18.1
2026-08-18
Docs qualify the OAuth login as remote-MCP, before a second one lands
Name it before there are two
docsdocsdevelopersoperators
Nine docs sites that said OAuth login now say remote-MCP OAuth login, so the shipped host flow stays distinguishable once nightjar auth login adds a second one.
#2853
· 2026-08-18
Docs honesty gate now checks that cited symbols exist in the tree
A citation that names nothing is not a citation
internaldocsdevelopers
A Today page that cites a symbol now fails CI if that symbol resolves to no source file.
#2857
· 2026-08-18
Artifacts now record the page they were produced against
Every artifact remembers where it came from
addednodedevelopers
Session artifacts now carry the page URL they were minted against, captured best-effort at mint time.
#2869
· 2026-08-18
v2026.08.17.2
2026-08-18
Declare the mcp serve command, its operation contract and its error family
Declared before it is built
addedclidevelopers
A repo can now declare its MCP entry as a command that names a saved login, rather than an HTTP entry carrying a credential in a header template.
#2828
· 2026-08-17
The SDK now refuses a publish that would ship an uninstallable package
Publish with the tool the manifest was written for
fixedsdkdevelopers
0.1.0 reached the registry uninstallable, because npm publish neither applies publishConfig nor rewrites a workspace range. The tree is fixed for 0.1.1, and a prepublishOnly guard now refuses the wrong publisher.
#2832
· 2026-08-17
The credential security guide promised a scope clamp that no longer holds
A gate is not a wall
fixeddocsoperatorsdevelopers
The published guide said a grant can never carry a write or admin scope. Since the owner-consent addendum an owner may consent to one, so the guarantee was false in the reassuring direction.
#2838
· 2026-08-17
The publish guard now covers every package, and builds before it checks
An empty package is a broken package
fixedsdkdevelopers
api-types 0.1.0 shipped with a correct manifest and an empty tarball, so the SDK installed and imported but failed every consumer tsc. The guard is now shared, and prepublishOnly builds first.
#2840
· 2026-08-17
v2026.08.17.1
2026-08-17
Document where the agent credential store lives, and why it refuses to guess
No fallback for a secret
docsdocsoperatorsdevelopers
The credential-security guide now states the store root, the NIGHTJAR_CREDENTIALS_DIR override, and why an unset home is an error rather than a fallback.
#2830
· 2026-08-17
v2026.08.16.2
2026-08-17
The token response now names which credential AND which instance
One stable anchor, one moving marker
addedcontroldevelopersoperators
The OAuth token response gains two value-free extension members: a credential id that is stable across refreshes, and a token instance id that is new on every refresh. Both are ids, never secret material.
#2794
· 2026-08-16
Reach claim now retires every superseded join token
One live key at a time
securitycontroloperatorsdevelopers
Claiming a reach grant now revokes the join tokens it supersedes, so an older secret stops authorizing a daemon join the moment a newer one is issued.
#2798
· 2026-08-16
Refuse to open a credential store on a root we cannot lock
A locked door in an open corridor is a locked door
securityclioperatorsdevelopers
Opening the credential store now locks and checks its directory first, and refuses rather than proceeding when it cannot.
#2800
· 2026-08-16
Add the MCP proxy credential-attach policy for ADR-056 C2
The credential goes one place only
addedmcpdevelopers
The stdio MCP proxy re-reads its credential per request, sends it only to the profile's pinned origin, and reports which credential it attached without ever printing it.
#2806
· 2026-08-16
Document the agent credential store's shipped storage guarantees
Storage is part of the security model
docsdocsdevelopersoperators
The credential security model now covers where an agent's own platform credential lives on disk, and what the file backend guarantees about it.
#2812
· 2026-08-16
Motto gate: arcs are no longer rejected for their flags
fixeddocsdevelopers
The changelog gate read an elliptical arc's flags and radii as coordinates, so any motto drawn with a curve failed the safe-band check wherever its art actually sat. Path data is now parsed per command.
#2817
· 2026-08-16
Guard the workspace member and node Dockerfile COPY invariant
A member with no COPY line is a build that cannot start
internalnodedevelopers
Adding a crate to the workspace without a matching COPY line in the node Dockerfile now fails a lane-tooling arm that names the crate, instead of failing the image build much later.
#2818
· 2026-08-16
Refuse a pasted credential where a saved login name is expected
A token is not a name
securitymcpoperatorsdevelopers
Pasting a Nightjar key where a saved login name belongs is now refused, instead of being repeated back inside the error message.
#2821
· 2026-08-16
Pin an MCP origin to an IPv6 address without naming a port
The brackets are the boundary
fixedmcpoperatorsdevelopers
A bracketed IPv6 literal without a port was refused, because the authority was split on its last colon and an IPv6 address carries colons inside the host.
#2822
· 2026-08-16
Changelog summaries may now name the identifier they are about
changeddocsdevelopers
The underscore enters the summary allowlist, so an entry can write NIGHTJAR_REQUIRE_DB_TESTS instead of circumlocuting it. Headlines keep the narrow set and stay scannable at chip size.
#2823
· 2026-08-16
Credential refusals name the profiles you have, never the one you typed
Answer the next question, not the last mistake
securitymcpoperatorsdevelopers
Pasting a credential where a profile name goes no longer puts it into an error message, and so into every log or screenshot that captures one.
#2824
· 2026-08-16
The changelog contract now tells you what to do when no component fits
Count the gap you cannot see
docsdocsdevelopers
The live contract now carries the rule for declaring changelog:none when no component fits, so an author meets it where they already look.
#2825
· 2026-08-16
v2026.08.16.1
2026-08-16
The credential leaves the environment
Read at request time, not at launch
addeddocsdevelopersoperators
ADR-056 decides the agent credential binding: a local multi-profile credential store consumed by a stdio MCP proxy that attaches authorization at request time, replacing the env-var Bearer header pattern that cost a five-hour incident.
#2759
· 2026-08-16
The access-request deep link no longer says a pending request is resolved
Say only what you can see
fixedconsoleoperators
Opening a request deep link while a different org is active told you the request was already resolved. It now says only that the request is not in this org's queue.
The deep-linked request is absent from the active org's queue. Before: the note declares it already resolved with nothing left to action. After: the note states only that it is not in this org's queue, and offers the org switch.
#2763
· 2026-08-15
Tell the two screenshot refusals apart, so nobody hunts a build that works
Two silences that need opposite answers
fixeddocsdevelopers
When a capture refuses because it cannot find your text, it now says whether the page rendered or not.
#2764
· 2026-08-15
The deploy verify takes a ref, so an expected build cannot be mistyped
Do not check for the mistake; remove the chance
changeddeployoperators
The expected build can now be given as any ref, resolved internally, instead of a copied commit id. A ref has nothing to transcribe, and a bad one is reported as a caller error rather than as a failed deploy.
#2770
· 2026-08-15
Name the hosted URL when the CLI cannot reach a Nightjar server
Say where else the server might be
changedcontroloperatorsdevelopers
When the CLI cannot reach a server it now names the hosted platform URL as well as the local options, so a first run against the cloud does not fail with only localhost advice.
#2773
· 2026-08-16
Stop a required reach test flaking when a sibling test reaps first
Assert the row, not the batch
internalcontroldevelopers
Three reach tests asserted on the reaper's batch report instead of on the grant they were testing, so a required postgres check could fail with a zero-scan signature.
#2776
· 2026-08-16
Changelog entries can name the CLI as their component
The audience arrived, so the slot opened
addeddocsdevelopers
The changelog contract gains a cli component, so a change to the command-line tool can be classified as what it is instead of borrowing a neighbouring slot.
#2778
· 2026-08-16
Assert reaper idempotence on the row rather than a global batch counter
Two sweeps pass, the row is unchanged
internalcontroldevelopers
Four assertions in the transport reap suite compared a globally-scoped batch counter, so a sibling test's candidate could red a healthy run while never asserting anything about the row under test.
#2783
· 2026-08-16
Type-check the Windows-only code that CI could never compile
No code ships that no compiler has read
addeddocsdevelopers
CI now type-checks every crate that contains Windows-only code, instead of skipping it in silence.
#2787
· 2026-08-16
Split the credential id so a stale token binding is visible
One id says which; only two say which one, now
internalclidevelopers
A session credential now carries a stable id and a per-refresh instance id, instead of one id that conflated them.
#2789
· 2026-08-16
Ask for a fresh reach claim code when the old one is lost
One lost code, one deliberate replacement
addedcontroloperatorsdevelopers
POST /v1/reach/ensure accepts remintClaim. Declare it and the outstanding claim code is revoked and replaced atomically; omit it and repeated polls reuse the live code exactly as before.
addedmcpdevelopers
The local reach ensure tool gains the same optional remintClaim argument, defaulting to false.
#2792
· 2026-08-16
Lock the credential store to its owner on Windows, and prove it
A permission you did not verify is a permission you do not have
securityclioperatorsdevelopers
On Windows the credential store's files are now restricted to their owner, and the restriction is read back and proven rather than assumed.
#2793
· 2026-08-16
Refuse a spec check that would compare the branch against itself
A file is not the file you asked for
fixeddocsdevelopers
A spec drift check could fetch its baseline from the wrong commit and report no drift forever, without ever failing.
#2796
· 2026-08-16
v2026.08.15.2
2026-08-16
Pickup grants now say how long the agent has to collect its key
A window you can see closing
changedconsoleoperators
Approving a pickup grant now shows when the collection window closes, instead of only saying the agent will fetch its own key.
#2724
· 2026-08-15
A map of how work is modeled here
The map names what the territory assumes
addeddocsdevelopers
A new repo-root reference, WORK CONCEPTS, explains how work is modeled: the units of design, work, planning, tracking, specification and memory, their relations, and which concepts are materialized versus convention versus implicit.
#2725
· 2026-08-15
Retire the hand-maintained changelog and preserve its releases on the site
Nothing was deleted, only moved
changeddocsdevelopersoperators
The changelog page now carries the two releases that predate the per-PR system, under a Before the per-PR system section, and the root file is a dated pointer rather than a second source of truth.
#2728
· 2026-08-15
Add a console screenshot tool that refuses to shoot a broken page
Better no picture than a plausible one
addeddocsdevelopers
changelog-capture takes the console screenshots this changelog has required since day one, and refuses rather than write one it cannot vouch for.
addeddocsdevelopers
It refuses an over-size capture before the browser starts, with the arithmetic and a remedy.
#2732
· 2026-08-15
Flag path segments that could hide a test input from the CI gate
A short list beats a silent zero
addedcontroldevelopers
A guard now keeps an annotated review list of every path built from chained join() literals, and fails only on one whose segments could compose a path the CI filter drops.
#2733
· 2026-08-15
Underline inline links on the docs site, and put that site in the a11y net
A link you can find without colour
fixeddocsdevelopersoperators
Inline links in docs prose are underlined, so they are distinguishable without relying on colour. Nine of twelve pages carried this, and it was the only serious accessibility violation on the whole site.
internaldocsdevelopers
The docs site is now covered by the accessibility job, which previously ran two other apps and had no test files at all for this one.
#2736
· 2026-08-15
Pin that an opted-out org can never be handed self-reach by the key template
A gate is only as good as its refusal
internalcontroldevelopers
The agent-key template's opt-in condition now has a negative arm on the mint path: an org that has not enabled agent self-reach must never be handed reach:self.
#2739
· 2026-08-15
Show the changelog reminder on the checks tab, and say when it was not checked
A warning nobody reads is not a warning
changeddocsdevelopers
The entry-contract check now writes its advisories to the run summary, where they are visible without opening a log.
fixeddocsdevelopers
Running the check on your own machine now says that it did not look at whether this branch owes an entry.
#2745
· 2026-08-15
A key mint now says when the agent template did not apply, and why
A 2xx should not hide a surprise
addedcontroldevelopers
The 201 from POST /v1/keys now carries templateApplied, plus a closed-enum reason when the agent-key template was eligible but something blocked it.
#2750
· 2026-08-15
Verify which build a site is actually serving, not just that it answers
The deploy already told us; nobody was reading
addeddeployoperators
A deploy can now be checked against the build it shipped, rather than against a 200. Both sites answer 200 on every path, so the old check could not tell a current site from one serving an old build.
#2760
· 2026-08-15
Links inside prose are underlined again, everywhere, by default
Colour is not an affordance
fixeddocsoperatorsdevelopers
An inline link in a block of text no longer relies on colour alone to be recognisable as a link.
#2761
· 2026-08-15
The public changelog stops linking where visitors cannot follow
A link a visitor cannot follow is worse than none
fixeddocsoperatorsdevelopers
Every reference on the public changelog page that pointed into the private source repository is now plain text, so a visitor no longer clicks through to a login wall.
#2762
· 2026-08-15
v2026.08.15.1
2026-08-15
The grant screen stops claiming a key was shown when none was minted
Say only what happened
fixedconsoleoperators
Approving an access request now reads the receipt before deciding what to show, instead of always revealing a secret.
The access requests screen, where approving a request decides between revealing a key and handing off to pickup.
#2692
· 2026-08-15
A malformed key-mint body now returns a readable error, not a bare 422
Refusing is only half; being readable is the rest
fixedcontroldevelopers
Sending a malformed body to the key-mint route now returns the normal error envelope, which names what was wrong. Previously the rejection arrived as a bare 422 with no envelope, so the explanation was discarded before the caller saw it.
#2693
· 2026-08-14
Add the changelog authoring flow: a finalize script and a skill
Draft it, then give it a number
addeddocsdevelopers
A finalize script promotes your draft into its PR directory and stamps the number.
addeddocsdevelopers
A changelog-entry skill covers the fields, the prose rules, and how to draw a motto.
#2695
· 2026-08-15
A person on the OAuth approval leg gets a page, not a JSON blob
A human leg deserves a human answer
fixedcontroloperators
The three browser-facing legs of the device-approval flow now render a titled HTML error page instead of the API's JSON error body.
#2696
· 2026-08-15
The changelog is a page you can read, not a file you have to find
Every change, drawn and dated
addeddocsoperatorsdevelopers
The docs site gained a changelog page that renders every shipped entry, newest first, with its drawing.
#2697
· 2026-08-15
Report a suppressed screenshot as a confirmed failure, not as never started
The capture ran; the answer never arrived
fixednodedevelopers
A screenshot withheld because a secret field could not be safely redacted now reports its outcome certainty as a confirmed failure, not as an operation that never started.
fixednodedevelopers
The same corrected certainty is visible to MCP clients reading the error envelope of a suppressed screenshot.
#2701
· 2026-08-15
Approving a device sign-in now works when you are signed out
The code survives the trip
fixedcontroloperators
Following a device sign-in link while signed out used to drop the code and leave you on the console with nothing to approve. The approval page now renders after you log in.
changedcontroloperators
If you belong to more than one organisation, the approval page now asks which one to approve as, instead of returning an error that named an HTTP header.
#2713
· 2026-08-15
The console tells you when your build is behind the changelog
You are three releases behind
addedconsoleoperators
A banner appears when the console you are running is not current with the shipped changelog, and links to what you are missing.
#2719
· 2026-08-15
Drive the device-grant approval walk against a real control
Assert the form, not the status
internalcontroldevelopers
The device-grant approval leg is now exercised end to end against a real control and a real postgres, covering the six states a fixture can hold honestly.
#2720
· 2026-08-15
v2026.08.14.7
2026-08-15
Add the illustrated per-PR changelog and its contract gate
Every PR tells its own story
addeddocsdevelopers
Every PR now ships a small illustrated changelog entry: what changed, who it affects, and a drawing.
addeddocsdevelopers
A CI gate validates every entry: schema, filing, prose, illustration and screenshots.
#2683
· 2026-08-14
Access request audits now name the human who approved them
A record that names a person
addedcontroloperators
An access request actioned by a signed-in human now records that person, not only the key they acted through. A row names a key approver or a human approver, never both.
#2684
· 2026-08-14
Refuse a mistyped access request instead of accepting it silently
A typo should not look like success
fixedcontroldevelopers
Filing an access request with a misspelled field now fails with a 400 that names the offending field. Previously the unknown field was ignored and the request was accepted, so a typo produced a scopeless request that looked like success.
addedcontroldevelopers
The create and status responses now echo back the scopes and delivery mode as recorded, including the defaulted delivery mode, so a caller can confirm what was actually stored.
#2687
· 2026-08-14
v2026.08.14.6
2026-08-14
Rotate a key with no paste: the operator initiates, the key picks itself up
The last paste, removed
addedcontroloperatorsdevelopers
Rotating an agent credential no longer moves a secret by hand. The operator initiates the rotation, and the replacement is minted only when the key itself collects it.
#2682
· 2026-08-14
Before the per-PR system
Releases before ADR-055 — the decision that introduced the per-PR changelog you are reading —
were recorded by hand in the project's root CHANGELOG.md. That file is now retired
and its contents are preserved here unchanged, so this page is the complete record.
v2026.06.28.1 — 2026-06-28
⚠ BREAKING — egress
intranet_mode is now enforced unconditionally. A cloud session's
tunnel reach to undeclared private/loopback hosts (RFC1918, CGNAT, IPv6-ULA
literal IPs, loopback IPs, and localhost-family names) is now denied unless the org sets intranet_mode=true in governance — regardless of the NIGHTJAR_TUNNEL_REQUIRE_DECLARED operator
switch. Previously, with that switch at its default (off), private/loopback tunnel reach was
permitted. Every org defaults to intranet_mode=false, so any org
relying on undeclared private or loopback tunnel automation must turn intranet mode on
(Settings → governance, org:admin), or declare the specific host/CIDR on the
network's allowlist (a declared target stays reachable even with intranet mode off). The
always-on egress floor (cloud-metadata 169.254.169.254,
link-local, platform-internal CIDRs) and the env screens
(NIGHTJAR_EGRESS_SCREEN_INTERNAL, NIGHTJAR_PLATFORM_CIDRS) are
unchanged — only the private/loopback class decision moved under intranet_mode. (#653; ADR-021 amendment.) Rollback: deploy/deploy.sh --version v2026.06.27.6.
Added
Org capture-policy v1 (#652): a per-org default capture_mode (minimal / standard / diagnostic / forensic — the one capture ordinal the node enforces on
the start_session wire), alongside the existing per-org network_log default (all four tiers, node-enforced). Both are
authored from Settings → Data governance (org:admin). Migration 0027 is additive and nullable (NULL = no org default → the session falls through to the
node default diagnostic), so existing orgs are unchanged. The other model knobs
(separate journal/screenshots/dom_perception, viewport_recording, credential_fill_window) are deliberately not authored: the node has no per-facet param, so a separate org column would
be inert. (ADR-015 §8.)
Cross-language summarize() parity gate (#651): shared fixtures
assert the Rust (replay.rs) and TypeScript (real.ts) journal-event
summarizers produce identical output; CI fails on divergence. (Codegen-unification of the two
summarizers stays deferred; one best-effort fallback arm is a tracked known-divergence.)
Tunnel egress-floor integration test (#649): asserts the never-allow floor
denies a cloud-metadata target on the live CONNECT data path, not just in isolation.
Internal / architecture
Arch-tier guard (#648): a new rs-foundation-data-tower tier in .nj-arch.toml machine-enforces the nightjar-data decomposition's
no-back-edge invariant — the three pure leaves (nightjar-net-registry, nightjar-perception-data, nightjar-session-data) may depend down on rs-foundation but the base can no longer depend up on
them. nightjar-profile-data deliberately stays at rs-foundation (the
base legitimately depends on its ProfileSpec).
v2026.06.27.6 — 2026-06-27
Console power-user kernel (ADR-030) landed, with the design-system debt burned
down: every list screen sits on the kernel and the legacy ExpandableTable/ExpandableRow primitives are removed; an accessibility
gate guards the showcase.
nightjar-data god-crate decomposition (#601): three leaf crates
extracted (nightjar-net-registry, nightjar-perception-data, nightjar-session-data), plus nightjar-svc and ws-bind split into per-responsibility modules.
App-Surface hardening (ADR-033 Slice 1): loopback-only egress floor with
DNS-rebinding / TOCTOU dial-pinning on attach/backfill/observer, a deterministic size cap on
imported app-evidence payloads, and a perceiveControls() advisory instead of a
silent drop.
Org-default network-capture tier + honest /trust disclosure (#416 v0, #420), plus a per-agent default network_log tier with New-session
pre-fill (#417).
Migration-gate hardening (fail on duplicate / non-increasing migration version), the
architecture size-gate turned into a tightening ratchet, and adversarial KMS envelope-crypto
tests.