rollup: 2026-09-29 ctkm-1 integration into main - #1700
Merged
Merged
Conversation
…ag (#1690) Signup invitation codes are now an operator choice. The requirement is behind the global, default-on `auth:invitation-code` feature flag, which replaces the `INVITE_CODE_REQUIRED` environment variable and can be toggled in Admin > Feature Flags without a restart. - Enabled (default): email signup requires a valid code; browser social signup can redeem one; native social token exchange still rejects first-time signup. - Disabled: email and first-time social signup succeed without a code. - Flag is global only; scoped overrides are rejected. The backend resolves it on every signup attempt and /api/v1/public/config reports the effective state. - Invitation-code admin page, API and CLI are retained; the page states when codes are not required. Organization invitations are unchanged. - Rollout: deploy backend before frontend. Deployments with INVITE_CODE_REQUIRED=false must disable the flag to keep signup open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
📊 Code coverage
Gate: line coverage must stay at or above the threshold. Ratchet plan (W21): Backend → 55%, CLI → 50%, Frontend → 30% by quarter end. |
Rework the OAuth consent page into the centered card used by connect links and channel-bot connections: circular NyxID mark, "Authorize application" heading with the requesting app highlighted, plain-language permission rows, and a trust note above Allow/Decline. Client ID, redirect and raw scopes move under App details. The Low/Medium/High scope badges are removed; they were client-side labels, not server decisions. Service access shows each service's catalog description (two lines max) in a scrollable list with edge fades. Customize toggles a picker that closes via Done or Save selection. GET /user-services list responses now include catalog_service_description. Form fields posted to /oauth/authorize/decision are unchanged. Adds a dev-only /oauth-consent-preview route with sample data and disabled decisions. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
the_same_question_is_not_worked_on_twice slept 300 ms after a Lark relay callback that returns 202 before recording the message. The instrumented coverage build on rollup PR #1700 took longer, so the reply target was not yet recorded. Poll the home thread (bounded to 10 s) until it is, keeping the assertions unchanged. Record the follow-up in the rollup notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The #1690 test 'allows email registration without a code when the flag is disabled' failed once in the rollup's frontend coverage run: the register call had not happened within waitFor's default 1 s. Use a 5 s timeout, as other slow frontend waits do, and record the follow-up in the rollup notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6 of 7 tasks
Re-authoring a service price deleted the retired Lago code's billing_rate_cache row, so every historical usage_meter row recorded under that code lost its only price and GET /billing/usage returned null costs; the Usage page then showed Unavailable for the service and for the Spend total. Grants were never the cause. - Price removal marks the rate row retired_at instead of deleting it; new reservations refuse retired rates, historical pricing keeps reading them, and a re-synced price clears the mark. - get_usage prices historical groups by grant-settled derivation, then the cached rate, then per-row reservation rates (exact Decimal128 credits, as exact settlement does), else null with grant credits still known. - The Usage page shows lower bounds (≥) with an unpriced-record count instead of Unavailable when only some records are unpriced. - Docs: glossary precedence, admin usage limitation, rollout note. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Backend Test and Backend Billing Smoke died five times out of seven
attempts on the 2026-09-29 rollup head with exit 143 ("The runner has
received a shutdown signal") four to five minutes into compiling the
nyxid test binary, before any test ran. The full-DWARF test binary
exhausts the hosted runner's memory during codegen and linking. Both
jobs now set CARGO_PROFILE_TEST_DEBUG=line-tables-only, which keeps
panic locations and backtraces and changes nothing for local builds or
the coverage jobs.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
13 tasks done
* feat(channels): add tracked bot setup links and signed callbacks * fix(channels): preserve bot creation calls in production builds * fix(cli): save bot webhook signing secrets to private files * ci: bound backend coverage debug information
16 tasks done
* fix(oauth): make Google Workspace grants optional Accept partial Google consent, remove seeded required-scope metadata across Workspace products, and show last reported grants in service details. * test(oauth): match optional Workspace seed wording * feat(oauth): show grants for every Google Workspace product * test(oauth): retain prior scope evidence when response omits scopes * ci: bound backend coverage debug info for hosted runners
ctkm-aelf
added a commit
that referenced
this pull request
Sep 30, 2026
* rollup: 2026-09-29 ctkm-1 integration into main (#1700) * feat(auth): gate signup invitation codes behind default-on feature flag (#1690) Signup invitation codes are now an operator choice. The requirement is behind the global, default-on `auth:invitation-code` feature flag, which replaces the `INVITE_CODE_REQUIRED` environment variable and can be toggled in Admin > Feature Flags without a restart. - Enabled (default): email signup requires a valid code; browser social signup can redeem one; native social token exchange still rejects first-time signup. - Disabled: email and first-time social signup succeed without a code. - Flag is global only; scoped overrides are rejected. The backend resolves it on every signup attempt and /api/v1/public/config reports the effective state. - Invitation-code admin page, API and CLI are retained; the page states when codes are not required. Organization invitations are unchanged. - Rollout: deploy backend before frontend. Deployments with INVITE_CODE_REQUIRED=false must disable the flag to keep signup open. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rollup): record 2026-09-29 ctkm-1 rollup Records #1690 (default-on auth:invitation-code signup gate), its reviewed head and squash commit, the main sync to e96a507, rollout notes and verification. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(oauth): redesign consent screen to match connection flows (#1701) Rework the OAuth consent page into the centered card used by connect links and channel-bot connections: circular NyxID mark, "Authorize application" heading with the requesting app highlighted, plain-language permission rows, and a trust note above Allow/Decline. Client ID, redirect and raw scopes move under App details. The Low/Medium/High scope badges are removed; they were client-side labels, not server decisions. Service access shows each service's catalog description (two lines max) in a scrollable list with edge fades. Customize toggles a picker that closes via Done or Save selection. GET /user-services list responses now include catalog_service_description. Form fields posted to /oauth/authorize/decision are unchanged. Adds a dev-only /oauth-consent-preview route with sample data and disabled decisions. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * test(nyxbot): wait for relayed message instead of a fixed sleep the_same_question_is_not_worked_on_twice slept 300 ms after a Lark relay callback that returns 202 before recording the message. The instrumented coverage build on rollup PR #1700 took longer, so the reply target was not yet recorded. Poll the home thread (bounded to 10 s) until it is, keeping the assertions unchanged. Record the follow-up in the rollup notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(rollup): record #1701 in the 2026-09-29 ctkm-1 rollup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(auth): allow the code-free registration test 5 s under coverage The #1690 test 'allows email registration without a code when the flag is disabled' failed once in the rollup's frontend coverage run: the register call had not happened within waitFor's default 1 s. Use a 5 s timeout, as other slow frontend waits do, and record the follow-up in the rollup notes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(billing): keep historical usage priced after price removal (#1702) Re-authoring a service price deleted the retired Lago code's billing_rate_cache row, so every historical usage_meter row recorded under that code lost its only price and GET /billing/usage returned null costs; the Usage page then showed Unavailable for the service and for the Spend total. Grants were never the cause. - Price removal marks the rate row retired_at instead of deleting it; new reservations refuse retired rates, historical pricing keeps reading them, and a re-synced price clears the mark. - get_usage prices historical groups by grant-settled derivation, then the cached rate, then per-row reservation rates (exact Decimal128 credits, as exact settlement does), else null with grant credits still known. - The Usage page shows lower bounds (≥) with an unpriced-record count instead of Unavailable when only some records are unpriced. - Docs: glossary precedence, admin usage limitation, rollout note. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * docs(rollup): record #1702 in the 2026-09-29 ctkm-1 rollup Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * ci: build backend test binaries with line-table debuginfo Backend Test and Backend Billing Smoke died five times out of seven attempts on the 2026-09-29 rollup head with exit 143 ("The runner has received a shutdown signal") four to five minutes into compiling the nyxid test binary, before any test ran. The full-DWARF test binary exhausts the hosted runner's memory during codegen and linking. Both jobs now set CARGO_PROFILE_TEST_DEBUG=line-tables-only, which keeps panic locations and backtraces and changes nothing for local builds or the coverage jobs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * feat(chat): open connector and channel setup in reusable overlays (#1707) * feat(chat): open connector and channel setup in reusable overlays * fix(chat): harden setup popup lifecycle and restore link focus * feat(channels): add tracked bot setup links and signed callbacks (#1705) * feat(channels): add tracked bot setup links and signed callbacks * fix(channels): preserve bot creation calls in production builds * fix(cli): save bot webhook signing secrets to private files * ci: bound backend coverage debug information * docs: record bot-link callbacks and rollup verification * fix(oauth): make Google Workspace grants optional (#1706) * fix(oauth): make Google Workspace grants optional Accept partial Google consent, remove seeded required-scope metadata across Workspace products, and show last reported grants in service details. * test(oauth): match optional Workspace seed wording * feat(oauth): show grants for every Google Workspace product * test(oauth): retain prior scope evidence when response omits scopes * ci: bound backend coverage debug info for hosted runners * docs: record Google OAuth grant fix in rollup --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> * feat: NyxBot guests use specialists' services at owner-set levels; Telegram bot creators are owners; Lark groups answer only bot mentions (0.38.0) (#1712) * fix: a Telegram bot created through NyxID knows its owner: the creating account is verified on link or first message, and Start greets instead of refusing * fix: only a creator bound by the owner's own setup challenge is trusted, in private chats; link-time grants are audited and NyxBot keeps the verify link as a fallback * chore: bump version to 0.37.2 * fix: guests use a specialist's services except deleting; Lark groups count only mentions of the bot itself * fix: guests are refused calls that look like deleting by what they send, and never raise approvals; Lark bot ids cached per app * fix: guest delete checks cover GETs, body method overrides, unparsable JSON and code fields; guests never run on the owner's approval grants * feat: owners set what guests may do with each of a specialist's services (read, use, all), from the agent page or by asking NyxBot; destructive operations come from spec markers, not word lists * test: agent fixtures carry guest_access * fix: guest access judges every requested method, keeps levels beside grants for rolling deploys, honours read-only specs and catalog markers on mounted specs; Drive trash and content replace are destructive * fix: grants form builds its request without an unused binding * fix: guest calls never carry method overrides; Calendar event and Bitable record updates are destructive; a re-granted service starts at the default guest level * fix: guests' default use is reading, creating and acting (no PUT/PATCH/DELETE); Aevatar's destructive markers stay unchanged and NyxID marks POST edits itself; only stored catalog contracts widen reads; override keys read as PHP reads them * fix: NyxID's per-operation x-nyxid-changes-existing (true for POST edits, false for PUT actions); override checks follow the body's content type; hosted overlays mounted by URL are catalog contracts; all-level grants say they include deleting * fix: only a catalog contract may say an operation only acts; method fields count when they name another changing verb, in JSON bodies too; ; separates fields; hosted overlays share one check * fix: override checks skip empty, text and binary bodies; hosted overlay lookups share NyxID's compiled copy without cloning * chore: bump version to 0.38.0 --------- Co-authored-by: chrono-kw <chrono-kw@users.noreply.github.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: chronoai-kai <kaiweichronoai@gmail.com> Co-authored-by: chrono-kw <chrono-kw@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Integrate six source PRs into
main. #1690: signup invitation codes become an operator choice, gated by the global, default-onauth:invitation-codefeature flag instead of theINVITE_CODE_REQUIREDenvironment variable. With billing already provisioning a wallet for every new account, whether registration stays invitation-only is now a runtime toggle under Admin > Feature Flags. #1701: the OAuth consent screen is redesigned to match the connection flows, with no change to the authorization decision it posts. #1702: the Billing → Usage page keeps historical usage priced after a service price is removed or re-authored. Price cleanup used to delete the retired Lago code'sbilling_rate_cacherow, so every historicalusage_meterrow recorded under that code lost its only price,GET /api/v1/billing/usagereturned null costs, and the page showed Unavailable for the affected service (Chrono LLM) and for the whole Spend total. Retired codes now keep their row, historical groups are priced by grant-settled derivation → cached rate → exact per-row reservation rates, and partially unpriced totals display as lower bounds. Grants were never the cause. #1707: connector and channel-bot setup links clicked in NyxChat open the reusable setup component in an in-page overlay, keeping chat in place while standalone URLs retain their existing behavior. Local demos require explicit user submission. #1705: platforms and agents can create tracked bot setup links and receive signed completion, cancellation or expiry callbacks; existing production Connector-link contracts are preserved. #1706: Google Workspace connections accept partial grants, including identity-only consent; product scopes are optional, and service details show the last Google-reported grant.Verification snapshot: 2026-09-30. The rollup contains six source PRs: #1690, #1701, #1702, #1707, #1705 and #1706. #1705 landed as
a29056ef8328ae3cfd5bcca51a352e1408163c04from validated sourced08d3d0c2fb2eedf0da13de21bd5048f6b797fe6; its complete landed tree equals the tested source tree. #1706 landed asc883ea0e350e5e7f7a14047e905aa0483e137a35from validated sourcea42bf8a892a214412aeb6ee71a5bac438f48cdde; its source and landed patch IDs match. Maince4414e6eedbdac2baf33c67dff71c6a38c071af(#1703) was merged normally as3b80d68f, retaining main ancestry. The shared bot-setup conflict with #1707 was resolved and tested; the CLI wizard was regenerated for the combined source. Final #1705 and #1706 source CI, CodeQL and Release checks passed. Post-merge push CI, CodeQL, and Release passed on docs-only commita2c786a7fd568b3f156dfe445c30f865d4c3ff07after squasha29056ef. The PR coverage job was stopped during slow, passing test progress; its unchanged rerun was superseded when #1706 landed. The rollup record now includes #1706 at head463ca56a; fresh rollup checks are pending. Required main review and the separately tracked #1702 follow-up remain open.Squash integration and preservation of code/history
All six squash integrations preserve their source patches, and the reviewed main history remains an ancestor of this rollup. Squash merging recorded each source PR as a new commit on the rollup; the source branches' individual development commits are not imported as ancestors, and no existing target commits were rewritten. If this rollup is itself squash-merged into main, main receives one combined commit; the landed squash commits will not become ancestors of main. This PR, the source PRs and the rollup branch ref record the provenance.
Verification went beyond commit ancestry:
e96a5078→dc5fb1b4) equals that of the landed squash delta (e96a5078→e7691afe):5121a2a6e53a82568f71683a8b58cfa3d93c896e.921e5c5e→fbf21ac1) and squash delta (921e5c5e→68ad6d81) share patch ID9737bd433cb0…, andgit merge-tree --write-tree 921e5c5e fbf21ac1reproduces the landed treea9eb28fb3601f102c777c5fcb4df7b64529503a9exactly.b98949e1→595ed4b3) and squash delta (b98949e1→c3d49700) share patch ID8a146dbbd181cf376a67c6573838770d2b228a4e, andgit merge-tree --write-tree b98949e1 595ed4b3reproduces the landed tree8f684a12f046fc81bf2ade427ca4a17fdb12d7e3exactly, which is also the complete source tree. The source branch was created from the rollup head itself, so no main-sync merge was involved.7a410d9b→9d6d4618) and squash delta (7a410d9b→012dd86f) share stable patch IDc7f68e947408a6e2881a3191a8989fd9b373cfc9. Both complete trees aref15e3e2cfc9e037bf71c652049b4f53b1c87fd5e;git diff 9d6d4618 012dd86fis empty, and the merge-tree check reproduces that tree exactly.git merge-tree --write-tree e96a5078 dc5fb1b4is clean and reproduces the exact landed treec5d36bbaf4de57d31e89e71427da120ff18ec68e, which is also the complete source tree. No source change was lost.3b80d68f5431585f3f628bdc376aa7f86fba840dtod08d3d0c2fb2eedf0da13de21bd5048f6b797fe6and landed squash delta share stable patch IDdc667b78bfb183574b91a365e7d3e1c7db454d05. The landed tree andgit merge-treeresult both equal the validated source treed63cd0f6141262cde6737c89ec9ea3deeec398d7.a42bf8a8and squashc883ea0ehave the same complete treec441d75b3d0f2cea08adebc6d4afb37580a05268; the merge-tree result reproduces it. The source and squash deltas from parenta2c786a7share stable patch ID0e7f97b85b9ff989f7aa29480725fa39a811abdf.cf02492band fast-forwarded to maine96a5078(fix(auth): support catalog skill assignment through SA key updates #1694–feat: NyxBot moves chat-app bots onto the Agent Event Gateway per platform feature flag, without tearing down working bots (0.37.0) #1699) before the squash. Its only conflict with DRAFT: Gate signup invitation codes behind a default-on feature flag #1690 was inbackend/src/services/feature_flag_service.rs, where main added the sevennyxbot:gateway-*flags alongside the newauth:invitation-codeflag. The resolution keeps both sides, and the pinned registry-key test lists every key.frontend/src/lib/feature-flags.ts,frontend/src/hooks/use-feature-flag.test.tsxandbackend/src/test_utils.rsauto-merged.Reproduce the check:
source=dc5fb1b4be000995027c90412701d66c97766588 squash=e7691afe605770e67128376bf87b610c5e8f37a8(orsource=595ed4b3f192aea999def3abf46b2b6dfce9b859 squash=c3d49700f98be5bb31f1beacb3700bb25564fbbd). Findgit merge-base "$squash^" "$source"and compare stable patch IDs for base→source and squash-parent→squash. Then comparegit merge-tree --write-tree "$squash^" "$source"withgit rev-parse "$squash^{tree}".Included changes and provenance
dc5fb1b4be000995027c90412701d66c97766588→e7691afe605770e67128376bf87b610c5e8f37a8auth:invitation-codefeature flag, replacingINVITE_CODE_REQUIRED. Invitation-code management is retained; organization invitations are unchanged.fbf21ac1e7dbed35656b777f64526d8d5bf0f867→68ad6d8146460ebd721158522c9fabea4256140e/oauth-consentto match the connect-link and channel-bot screens. It shows plain-language permissions, collapses app details and removes the client-side risk badges. Service lists gain catalog descriptions and scroll.GET /api/v1/user-serviceslist rows add optionalcatalog_service_description. The/oauth/authorize/decisionform is unchanged.595ed4b3f192aea999def3abf46b2b6dfce9b859→c3d49700f98be5bb31f1beacb3700bb25564fbbdbilling_rate_cacherowretired_atinstead of deleting it (fresh_raterefuses it for new reservations; historical readers keep it; a re-synced price replaces it).GET /api/v1/billing/usageprices historical groups by grant-settled derivation, then the cached rate, then exact per-row reservation rates (rate × quantity in Decimal128 credits, as exact settlement computes), else null with grant credits still known. The Usage page shows≥lower bounds with an unpriced-record count instead of Unavailable when only some records are unpriced. Docs: glossary precedence and the admin-usage limitation,LAGO_SETUP,PLATFORM_KEYS_AND_INFERENCE,USAGE_BILLING_LAGO_SPEC,ENV,CLAUDE.md.9d6d4618b9fd4156f5686402a54fb57b6fdb96e6→012dd86f840e77fcb0486120e965b430d4dcc25dConnectLinkContent; channel setup opts into staying in place. Existing standalone URLs and default navigation remain supported. Includes explicit-submit demo fixtures, popup lifecycle/recovery fixes, focus restoration, tests and chat documentation.d08d3d0c2fb2eedf0da13de21bd5048f6b797fe6→a29056ef8328ae3cfd5bcca51a352e1408163c04a42bf8a892a214412aeb6ee71a5bac438f48cdde→c883ea0e350e5e7f7a14047e905aa0483e137a35Rollup-only commits:
921e5c5e,62dd17acand7304e0a7add and updatedocs/rollups/rollup-2026-09-29-ctkm-1.md.7848cce1fixes a test only.handlers::nyxbot::tests::the_same_question_is_not_worked_on_twice, inherited frommainfeat: NyxBot one context for the owner across chat apps; the same question is never worked on twice (0.36.0) #1697, failed once in this PR's backend coverage run. It slept a fixed 300 ms after a Lark relay callback that returns 202 before recording the message. It now polls, bounded to 10 s, with unchanged assertions. It passed 10 of 10 isolated local runs. This fix landed onmainthrough this rollup (rollup: 2026-09-29 ctkm-1 integration into main #1700).b98949e1fixes a test only. DRAFT: Gate signup invitation codes behind a default-on feature flag #1690'sAuthFlow — register > allows email registration without a code when the flag is disabledfailed once in frontend coverage. The register call had not happened withinwaitFor's default 1 s. It passed in the other three frontend runs on that head and on rerun. It now waits up to 5 s, like existing slow frontend waits.62dd17ac, the push run's rerun passed both Backend Test and Coverage (Backend). That was the full backend suite, including feat(oauth): redesign consent screen to match connection flows #1701 and the NyxBot fix.7a410d9bis CI-only. On head7304e0a7,Backend TestandBackend Billing Smokedied five times out of seven attempts with exit 143 ("The runner has received a shutdown signal") four to five minutes into compiling thenyxidtest binary, before any test ran; the same job passed on that head's pull_request run (the full backend suite), and the 04:17 pull_request run had hit the identical failure on an earlier head. These logs establish runner shutdown during compilation; memory pressure from full debug information is a hypothesis, not a measured OOM diagnosis. Both jobs now setCARGO_PROFILE_TEST_DEBUG=line-tables-only, which keeps panic locations and backtraces and changes nothing for local builds. feat(channels): add tracked bot setup links and signed callbacks #1705 subsequently applies the same profile to both backend coverage jobs while preserving instrumentation and thresholds. These profile changes landed onmainthrough this rollup (rollup: 2026-09-29 ctkm-1 integration into main #1700).463ca56aadds fix(oauth): make Google Workspace grants optional #1706 provenance, behavior, verification and the scope-evidence limitation to the rollup record.Code review and behavior verified
These statements describe the reviewed implementation; they do not guarantee that every possible execution has been tested.
The bullets below cover #1690. #1701 landed in the rollup after this review. Its behavior is as described in #1701 and verified by its 31 consent-page tests; its code has not been independently reviewed here. Its own CI Backend Test job was lost to a runner shutdown, so this rollup's CI is the first backend run over it.
auth:invitation-codedefaults to enabled, so deployments that required codes keep requiring them until a platform admin disables the flag. No restart is needed.subject_token_type=id_token) still rejects first-time signup.GET /api/v1/public/configreports the effective requirement.#1702 was reviewed line by line by Claude Fable 5.1, by a Claude Opus 5.5 adversarial pass (nine minor findings, all resolved before merge), and by two GPT-6-Astra passes (pre- and post-rebase). Astra verified that the exact-
Creditsvaluation matchessettle_usage_funding, that the grant-settled derivation is sound for both pre-cutover (whole-credit ceiling) and exact rows, that null handling stays conservative, and that the frontend availability rules match the emitted rows. Behavior verified for #1702:complete_price_removal, the lane-cleanup branch andcleanup_componentsretire the code's cache rows (retired_at) instead of deleting them.fresh_raterefuses a retired row before its staleness check, so new reservations cannot size holds from a removed price;find_rate,settlement_rate_pico,estimate_credits, the usage handler and admin usage keep reading retired rows. A full-row re-sync (pricing or Lago plan refresh) replaces the row and clears the mark.get_usage: exact persisted settlements are unchanged; for a group's historical rows: (1) all settled with a zero wallet debit and zero consumed allowance units → gross = grant consumption exactly; (2) model-specific then generic cached rate; (3) every row carries a reservation rate → per-rowrate × quantity ÷ 1e12in Decimal128 (allowance = rate × units), summed and read back throughCredits::from_bson(fails closed on overflow); (4) otherwise null gross/wallet/allowance with grant credits still reported. Legacy Int64wallet_charge_creditsandamount_microskeys are honored.≥ nlower bounds with an unpriced-record count when some charged rows are unpriced; "Unavailable" only when no charged record is priced; free rows contribute zero but never make a total known; groups sort by their known sum. Pending/Acknowledged/Free semantics are unchanged.≥) sums use the rounding display formatter. A follow-up source PR (active-first rate lookup,created_at-gated settlement, transactional sync/retirement fences, plan refresh preservingretired_at, exact 12-decimal partial formatting, with regression tests) is in progress and will be integrated into this rollup before main review completes.#1707 received an initial Fable 5.1 adversarial review. A later Fable attempt was unavailable because Claude usage credits were exhausted; the final independent review used the available default model and reported no blocking findings after verifying all three audit fixes. This is not a claim of final Fable sign-off. Behavior verified for #1707:
/connect/nyx_clk_<token>and/channel-bots/connect/<platform>URLs. Page and overlay render shared setup content. Modified clicks, unrelated/external links and direct full-page routes retain browser behavior. Channel query values are limited to label/org. Shared link components stay unaware of overlays; backend/message protocols are unchanged.stayInPlace, preserving all existing callers' navigation defaults./assistant?mock=1&nyxbot=1URL works without automated-test setup and persists the selected engine within the tab. Entered fixture credentials are not stored.Tracked bot setup links (#1705)
Platforms and agents can create a single-use bot setup URL through
POST /api/v1/channel-connect-linksornyxid channel-bot connect-link, send itto the human owner, and receive signed
channel_connect.completed,channel_connect.cancelled, orchannel_connect.expirednotifications. Thehosted page is
/connect/bot/{token}. An optionalcallback_urlreturns thebrowser after the owner acknowledges any one-time setup secret.
--webhook-signing-secret-fileand saves it to a new file (mode0600on Unix);terminal and JSON output contain only the path and signing key ID. Existing
files and symlinks are rejected before link creation. OAuth apps reuse their
registered connection webhook and redirect policy.
public HTTPS destinations with DNS pinning, disabled redirects, and a separate
app quota. Agent Keys can create, read, and cancel requests; completion requires
an authorized human and preserves the owner, platform, and label from creation.
(existing token and native creation), Discord, Slack, Lark, Feishu, WhatsApp, X,
and Aurinko email. Platform eligibility and manual/managed setup use the shared
adapter registry. OpenClaw’s separate integration and botless device channels
are outside this registration flow.
bot_statusandwebhook_registeredwith the platform’s ingestion mode to determine readiness.Manual provider setup may remain, and polling platforms do not universally
require
webhook_registered=true.tokens, events, standalone browser flows, webhook client behavior, and quota. Ordinary bot
setup continues through the original service entry points.
docs/API.mdanddocs/CHANNEL_BOT_RELAY.md; published CLI/web guides and the agent playbookcover creation, signing, retries, expiry, and callback setup.
regressions cover tracked setup and existing Connector-link behavior.
The shared setup-component conflict with #1707 preserves chat overlays and
tracked-link one-time results. Main #1703 was merged into the rollup as
3b80d68f; the CLI wizard was rebuilt from the combined source and its Rustfreshness test passed. Existing main history remains an ancestor of the rollup.
CI repairs keep ordinary bot creation using its existing service functions,
resolve strict Clippy warnings, save CLI webhook signing secrets in private
files instead of logging them, and apply
CARGO_PROFILE_TEST_DEBUG=line-tables-onlyto both backend coverage jobs. Tests, coverage instrumentation and thresholds
remain enabled. The high-severity CodeQL logging alert was fixed in source,
without dismissal or suppression.
Optional Google Workspace grants (#1706)
All seven Google Workspace product presets treat requested OAuth scopes as
optional. A connection can complete with only identity scopes even when its
initial request included Drive, Calendar and Gmail permissions. Startup
removes old seeded required-scope metadata while preserving unrelated custom
requirements. Gmail sending remains a default request, not a required grant.
AI Service details show Google's last reported scope list and derived product
access. Refresh updates that list when Google supplies scopes; an absent scope
response can leave the prior list in place. Ordinary Google API calls do not
return a fresh grant list, so the display does not verify scopes on every use.
Google rejects operations that need a scope the token lacks. Existing grants
are unchanged; users must reconnect to approve additional scopes.
Validation evidence
#1705 final source
d08d3d0c2fb2eedf0da13de21bd5048f6b797fe6: CI, CodeQL and Release passed, including backend tests/coverage, baseline coverage comparison, workspace Clippy, KMS builds, frontend/CLI tests and coverage, wizard freshness, image inputs, billing smoke and all CodeQL analyses. The PR has no open code-scanning alerts. Local integration checks passed 134 focused frontend tests, 25 Playwright browser cases, targeted ESLint, the production build and the regenerated wizard freshness test. Earlier focused validation passed 19 bot-link backend tests, 180 compatibility regressions, 92 CLI tests and 18 documentation tests; the backend groups overlap by one test.#1706 final source
a42bf8a892a214412aeb6ee71a5bac438f48cdde: CI, CodeQL and Release passed against the latest rollup base. CI includes backend tests, both backend coverage jobs, frontend tests and coverage, Clippy, Rust feature builds, image inputs, billing smoke and the pipeline gate. Local focused verification passed 159 frontend tests, TypeScript, ESLint and Rust formatting. The landed squash has the same stable patch ID as the source and matches thegit merge-treeresult exactly.Full integration CI on reviewed code
dc5fb1b4: CI, CodeQL, Release. Checked through GitHub check results and job logs:CLI, Mobile, SDK, Oracle worker and Cursor plugin jobs were skipped by path detection for that earlier #1690 run. Later #1705 changes include CLI work; its source CI exercised those jobs. The existing invitation-code CLI commands are unchanged.
The first run on the pre-sync head
15cb5f07had one Backend Coverage failure: the runner received a shutdown signal (exit 143) mid-compile. It passed on rerun; no test failed.Full integration CI on #1702's source head
595ed4b3(already on the rollup baseb98949e1): CI, CodeQL, Release. All 24 checks passed and 10 were path/release skips, with no failures: Backend Test (nextest), Coverage (Backend and Frontend), Frontend, Rust Format, Rust Clippy, the AWS/GCP KMS feature builds, Backend Billing Smoke, Backend Image Inputs, CLI Wizard Bundle Freshness, Release Integrity Manifest and CodeQL (actions, JS/TS, Python, Rust). Because the landed tree equals the source tree, this run exercised exactly the code now on the rollup.Fresh local verification on the merged tree against a MongoDB replica set:
nyxbotgateway flag tests.billing_integration_tests::usage,services::billing::{pricing,reservation,tests,funding,reconcile,meter,exact_tests}andhandlers::services::tests— 141 passed, 0 failed;cargo clippy -p nyxid --all-targets -- -D warningsclean; frontendeslint0 errors, vitest 66/66 for the billing and credits files,npm run build(type-check) passes.These were selected tests, not a new full-suite run.
#1707 source validation at
9d6d4618: CI, CodeQL, Release. All 13 applicable checks passed; 19 path/release checks were intentionally skipped. This source PR changes frontend/docs only, so source CI skipped backend tests. The rollup's post-merge checks exercise the combined changes.Two stale standalone Telegram test selectors were corrected. Default-concurrency local unit runs hit unrelated routing/auth timing limits; the complete suite passed with three workers and unchanged assertions, and unmodified default-concurrency CI also passed. Live external connector OAuth providers were not exercised; automated tests cover recovery/lifecycle.
Post-merge checks on
012dd86f: push CI, pull-request CI, CodeQL, Release. Three backend coverage jobs failed during compilation with runner shutdown/exit 143 before tests ran (PR head, PR base and push head). Both frontend jobs passed. The coverage profile mitigation landed through #1705 ata29056ef. #1711 was initially closed as a duplicate, then repurposed at the user's request into a broader CI reliability/speed enhancement targetingmain. The final #1711 heade1585ea9adds pinned compiler/test/coverage/database inputs, at least 8 GiB swap on heavy backend runners, resource diagnostics, bounded setup and jobs, exact base-report cache identity, cancellation of obsolete PR scans, Mobile aggregation and removal of unused coverage-report passes. It also fixes a separate direct-group callback test race introduced by #1712, using test-only completion synchronization; the earlier same-question timing fix (7848cce1) and line-table profile already landed through #1700. Production behavior is unchanged. Final CI, CodeQL and Release passed on the merge with main14d76f4a, including both backend coverage jobs. Full backend nextest passed 6,873 tests (2 existing skips). Backend head/base coverage executed the same 6,860 named tests and outcomes (6,858 passed / 2 ignored / 0 filtered) across the same 509 files; the only denominator difference is one added measured test-hook line. Head/base coverage is 87.44% backend / 72.45% CLI / 71.00% frontend, with unchanged gates of 73% / 64% / 15%. Final head/base coverage sampled 3.259/3.310 GiB swap, above the old 3 GiB capacity. These measurements support additional reserve and preserved coverage; they do not prove elimination of future infrastructure failures or a controlled speedup. #1711 is ready for review; main requires one approving review before merge. Both backend coverage jobs now useCARGO_PROFILE_TEST_DEBUG=line-tables-only, preserving instrumentation, full test commands and the 73% gate. #1705's source CI passed; the independent #1711 candidate also passed all 30 applicable checks (4 intentional skips), with 6,826 backend coverage tests passing and 87.43% line coverage in run 36716209962. These successful runs validate compatibility, not a proven elimination of infrastructure failures.Backend coverage reliability audit, September 30: 17 inspected failed coverage job executions comprise 16 runner shutdowns during compilation and one assertion failure; none failed the coverage-percentage threshold. This is a diagnostic sample, not a repository-wide failure rate. It includes failed jobs within later-cancelled workflows; some history API requests returned 502/504. Three workflows later passed on the same actual checkout commit, confirmed in logs: 36662907994 (shutdown twice, then 6,817 tests / 87.39%), 36670664278 (shutdown, then 6,817 tests / 87.38%), and 36680454361 (shutdown, then 6,823 tests / 87.40%). The assertion was
google_mail_callback_accepts_partial_grantson the separate Gmail investigation branch (job 109880567254): expectedNone, observed retained fixture scopeopenid; this is a test/behavior mismatch, not established intermittency. The earlier NyxBot fixed-sleep timing flake is separately addressed by7848cce1above.The compilation-shutdown signature also occurred in the older serial coverage workflow on September 25: 36111800751 and two attempts of 36113291552 passed head tests, then lost runners during base compilation. The evidence does not establish OOM, exhaustion of GitHub-wide compute, or a before/after failure-rate increase attributable to #1669. Next reliability work should record resource peaks and resolved coverage inputs, distinguish build/test/report/cancellation outcomes, cancel obsolete PR scans, and remove duplicate push/PR validation only when actual tested trees and inputs are equivalent. Preserve all suites, thresholds and release gates while tuning worker counts against measured resource use and latency. An unchanged control rerun of
36715953490was cancelled after approximately 92 seconds and is inconclusive; do not keep rerunning obsolete rollup revisions.Deployment and remaining acceptance
INVITE_CODE_REQUIREDis no longer read. Deployments that currently setINVITE_CODE_REQUIRED=falsewill require invitation codes after deployment until a platform admin disablesauth:invitation-codein Admin > Feature Flags. Plan that toggle together with the rollout if public signup must stay open without interruption.retired_atand could still reserve against a removed price until the 900 s rate TTL (BILLING_RATE_CACHE_TTL_SECS) expires; deletion refused immediately. The new field is additive; no migration is required, and rows deleted before this change stay unknown on the admin usage page.docs/rollups/rollup-2026-09-29-ctkm-1.md.7a410d9b: push and pull_request runs both green (Backend Test, Backend Billing Smoke and Coverage (Backend) passed on the first attempt with line-table debuginfo).auth:invitation-codesetting for each environment before rollout, and complete required main review before merge.🤖 Generated with Claude Code