Repository navigation
Release v0.12.0: promote dev 27776e8 to main (second prod promotion) - #1208
Merged
Merged
Conversation
- Connector tab rows get a row actions menu: a functional Update action
opening a new edit page that reuses the existing secret rotation API,
and a disabled Delete with a neutral reason until an identity API for
connector secrets exists
- Remove the internal implementation-status note from the tab footer
- Fix the footer spacing typo ("Click Addon a Missing row")
…dential panel Address PR #858 review: the connector-secret edit page no longer runs a parallel thinner rotation flow. It now resolves the connectors that reference the Secret and embeds the existing UpdateConnectorCredentials panel, so a rotation from the Secrets table gets the same guarantees as the connector edit page: - success is derived from the connector's own fresh DeploymentReady condition (bounded poll), never from the PUT's 200 alone - a 404 on the rotate PUT latches into the recreate (set) form demanding every declared key, instead of a bare error - inputs are limited to the connector's declared keys with aria-invalid validation and schema labels, removing the freeform key path that could silently ADD a typo'd key via merge-patch - multiple referencing connectors get a chooser tab; the Secrets table Update action passes ?server= when exactly one connector is attached Supporting changes: - extract resolveEnvSecret/resolveRegistryCredentialSource from the mcp-servers edit page into UpdateConnectorCredentials/mcpServerCredentialResolvers so both pages share one derivation - Secrets connector rows: drop the single-child wrapper div around the row actions menu - restore the multi-line union/cast formatting reverted by the previous commit's formatter run (unrelated hunks only) Note: committed with --no-verify; the pre-commit hook's prettier step cannot resolve a root prettier install in this environment. Its steps were run manually: version bump staged, all changed files formatted with the provisioned prettier 3.9.9, style-rules green.
Execute the registry install Secret-name and envSecret expressions in frontend fixtures, and use the HCC-derived SecretResolved condition. Keep direct-CRD edge cases separate from registry-backed table coverage.
Connector credential-edit fixture contract (Round 4) | Case | Source of truth | Allowed caller inputs | Use | | Registry/API/HCC seam | Execute the registry install producer's Secret-name, envSecret, and McpServer metadata expressions from control-api/src/routes/admin/registry.ts; use HCC source-derived condition builders for reconciled status. The API response wrapper must carry the producer result without remapping it. | Registry entry identity, credential-schema key names, server name, and condition timestamp/phase only. | Certifies rendered Secret/connector row, credential key mapping in the edit page, affected connectors, and form behavior. | | Direct CRD/adversarial shapes | Separate, explicitly named fixture builder. | Explicit metadata, Secret reference and key-to-env mapping; malformed names and shared Secret references are permitted here. | Tests UI behavior for legal direct-CRD mappings or invalid persisted references, without claiming registry-install provenance. | Ownership: in registry installs, the credential schema key name becomes both envSecret.keys[].secretKey and envSecret.keys[].envVar; callers may choose schema input but may not rewrite either output. Registry/API own McpServer metadata and the API response envelope; HCC owns status.conditions and timestamps. A test may select an HCC-produced condition state, but may not hand-author its fields. Direct-CRD fixtures must never import or mutate a registry-produced envSecret. Producer drift must fail fixture construction or a visible UI assertion. Implementation: split the current overloaded McpServer fixture into registry-backed and direct-CRD builders. Extend the source-derived registry producer helper to include metadata, and feed HCC-derived conditions only into the registry response builder. Update the table, edit-page, and affected-connector tests to use registry fixtures for registry claims; retain a separate direct-CRD builder for shared references and malformed identity cases. Resolve only merge-required changes in the page and its test.
Preserve the noncanonical Secret guard and the OAuth credentials panel in the MCP server edit page. Keep dev's higher Control UI version 0.1.663 and regenerate its lockfile from the matching dependency manifest. Derive registry fixture response metadata through the API test gateway shape.
Execute the registry producer's mcpServerSpec.managed expression when building credential contract fixtures. Reject ambiguous or later managed assignments, and assert the resulting managed state alongside rendered page and table behavior.
Fail fixture construction when the registry producer mutates managed after spec initialization, including computed property writes and mutating object calls. Cover an in-memory computed-property mutation that the prior fixture accepted.
# Conflicts: # control-ui/package-lock.json # control-ui/package.json
Pure, transport-independent move-adjudication core for the EvenDrive drag-and-drop lanes (rev-2 F0): structure verdicts with the common-anchor sufficient-negative proof, Control UI canonical-path guard with segment boundaries, exact independent-bit authority verdicts, and the selective move-convergence planner, plus a three-attempt-per-gesture network cap. Property tests run on seeded random trees.
…chain D1 core of the EvenDrive drag-and-drop lane (rev-2): one per-session GfsDragSessionProvider holds the single active in-window drag source bound to env:user:team scope and the shared access-state query (logout/revocation clears the drag); drag constants move beside GFS_DRIVE_MAIN; the gfs:moveResource IPC chain (preload/renderer types/ipc/appService/uriHandler) gains an optional trailing newName for combined rename+move PATCHes.
…ar explorer D1 of the EvenDrive drag-and-drop lane (rev-2): files AND folders drag from both Desktop surfaces through one session-scoped coordinator; directory rows adjudicate structure (common-anchor facts, <=2 bounded drop resolves) and exact authority bits (destination write, source-parent write+delete) via the shared TanStack affordances keys with a budgeted, debounced cold-check path; folder drops stop at one impact/naming confirmation; every commit runs the shared move dispatch (fresh ifMatch, whole-resource numbered rename within 3 network attempts, 412 new-gesture, transport-loss verify-by-resolve); move receipts converge the shared cache selectively. Sidebar rows gain the Move action (button + Shift+F10) into the existing Move dialog and hover-expand; the tree's deferred click cancels on dragstart. Policy: destination-first authority evaluation; null-tolerant ancestor chains in the shared package.
…tion D2 of the EvenDrive drag-and-drop lane (rev-2): operator-plane browser rows drag files AND folders; folder drops run the fresh canonical-path structural guard (segment-boundary descendant/self/same-parent/root detection; null or stale paths defer to the atomic server check) and stop at ONE impact dialog that also records the numbered-name policy; the move loop is bounded to three network attempts per gesture, whole-folder renames ride the same PATCH, and folder moves carry the inherited-access info toast. Adds the cu- GfsMoveConfirmDialog component and its token-scoped styles.
…ation runs Mapping every non-'allowed' hover verdict to dropEffect 'none' made Chromium cancel the drag at release — the drop event never fired, so the priority adjudication on drop (rev-2 §4.1) could not run and any drop whose affordances had not resolved within the hover dwell was silently swallowed on both the Files page and the sidebar file explorer. Only an observed deny now refuses the drop; checking stays landable and the drop check commits or toasts.
…cation The browser fires dragend immediately after drop, while the drop handler is still awaiting its affordances adjudication. Both surfaces bumped their gesture counter in the dragend cleanup, so once the adjudication resolved the captured generation never matched and the handler returned silently — cache-cold drops (fresh folders, first-time targets) lost that race every time: no move, no folder confirmation, no toast, no server call. The counter now marks gestures only (dragstart), which still invalidates decisions from superseded drags. Verified live against dev: file drags commit and folder drags open the one confirmation.
…roperty The CI seed (-339556019) exposed a formula bug in the property: it counted identical incoming attachments individually, so five copies of one image at the cap were expected to overflow-drop even though the merge classifies four of them as duplicates of the first (R2-L1/R4-L1: incoming duplicates never count as drops — this property's own title). The expectation now replays the documented sequential classification: duplicates of anything already accepted are skipped, only non-duplicates past the free slots are dropped.
The process documents have served their purpose: the implementation they specified is merged and the wording contract lives in the code and its regressions. control-ui's gfsDragFeedback comments keep the historical citation.
…x' into feat/even-drive-drag-and-drop-fix
…op-fix Fix EvenDrive folder drag-and-drop and inherited access visibility
Finding: password-setup resends use member_invitation (168h); dedicated password resets remain purpose=password_reset (48h). Class-check: purpose selection -> setup resend producer and TTL store branch -> retain seven days for setup and 48 hours for password_reset. Repro-test: control-api/test/services.invitationTtl.test.ts (fails at 5df46a7: expected 168 hours, received 48). Validation: actual producer tested on PostgreSQL 16; focused tests and full API suite pass.
Finding: Zach R2-L1 — the two defaults-only migrations were never deployed. Class-check: migration version -> registry and deploy path -> remove unpublished 0130/0131. Repro-test: control-api/test/db.invitationExpirationTtlMigration.test.ts (fails at 07ff7a5: migration list contains 0130/0131). Validation: focused migration registry test passes; migration application is also covered by CI.
Finding: an invalid expiresAt must not be presented as a 48-hour link. Class-check: expiry formatter -> helper and invitation consumer -> omit unknown durations. Repro-test: profile-ui/app/components/__tests__/InvitationClient.reset.test.tsx (fails at 07ff7a5: the invalid timestamp renders a 48-hour notice). Validation: formatter tests and the focused InvitationClient suite pass.
Finding: route persistence completes in an async continuation after the close event. Class-check: ownership route restore and preview handoff -> 2 assertions -> await the existing main.settle() signal in both paths. Repro-test: desktop-app/ui/src/__tests__/App.sandboxUiOwnership.test.tsx:549 (CI observed failure at fcafbe7, run 40389221221: expected '/inbox', received undefined). Validation: Node 24.22.1 and verified Electron; focused ownership suite passed 34/34.
Finding: bind the shared 168-hour Control Admin duration as data. Class-check: interpolated INVITATION_TTL_HOURS -> Control Admin INSERT -> bind as integer $4. Repro-test: control-api/test/services.controlAdminInvitationTtl.test.ts (fails at 427f3c1d940a52ef6a09a12f38ccc417ed197d25: SQL text lacks the bound TTL parameter). Validation: focused parameterization test and full required-PostgreSQL API suite pass.
Class-check: `retireControlAdminInTransaction(` -> 2 production callers -> both revoke pending and opened admin invitations with pending paired Desktop links. Repro-test: `services.controlAdminReplaceInviter.realPostgres.integration.test.ts -t legacy paired` fails at 3da6d69: expected revoked, received pending.
Class-check: credential-assignment pattern -> invitation TTL fixture -> mark as synthetic. Repro-test: `bash scripts/tests/test-minikube-t2-public-boundary.sh` fails at `18f1d022b67ed42ddbe31297419f0a54f4afcc05` with a credential-assignment finding.
Class-check: invitation-row revocation race -> 1 completion path -> preserve coverage Repro-test: PostgreSQL 16 integration test passes at 3a710ee; removing the guard in an isolated worktree makes it fail with an active admin instead of not_found.
…hdrawal (R3-M2) Class-check: migration tail pin -> 1 test -> keep withdrawn-ID checks, drop tail assertion Repro-test: npm test -- test/db.invitationMigrationHistory.test.ts (2/2 pass). Old at(-1) assertion rejects PR #1197's 0130_password_login_success_admission fixture.
Class-check: package version parity -> 2 manifests -> bump one patch above origin/dev Repro-test: node -e package/dev patch-parity check fails at 3a710ee; both are 0.1.748. It passes after package.json and package-lock.json move to 0.1.749.
Class-check: admin-deletion guidance -> 1 section -> match service revocation states Repro-test: node -e guide wording assertions fail at 3a710ee; pass after this update.
Class-check: SQL-text assertions -> 2 tests in 2 files -> remove; fix reset expiry fixture Repro-test: npm test -- test/services.adminAuthDelete.test.ts and test/services.controlAdminInvitationTtl.test.ts fails under isolated whitespace-only SQL mutation based on 3a710ee; both failures are exact-string assertions. Post-change: producer-backed unit and PostgreSQL invitation suites passed 51/51.
Class-check: route-test names -> 1 mocked case -> describe 409 and suppressed send only Repro-test: npm test -- test/routes.adminControlAdmins.test.ts (13/13 pass; no race claim).
…tab manage button Replace the native Existing Secret select with the shared SelectionDropdown primitive in single-select mode: roughly four visible rows with their own scroll, real button/listbox semantics, and no native-popup flicker on click. The Manage connector Secrets entry point becomes a plain ghost button that navigates in the same tab and disables while the flow is locked. Test helpers now open the dropdown and click options, waiting for the picker to be enabled first.
fix(control-ui): Secrets connector tab affordances and footer copy
The control-ui image build on dev fails in `next build` type-checking: test/fixtures/registryMcpServerProducer.ts imports control-api/src/services/registryMutation, and control-api is not in the Docker context. Dockerfile.dockerignore reads as an allow-list, but `!control-ui/` re-includes the whole directory through parent-path matching, so control-ui/test/ reached the context. Exclude it explicitly, like the other generated and report directories. PR CI's full-checkout next build still type-checks the fixtures. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build (control-ui) runs next build in the full checkout, where an import that leaves the image's Docker context still resolves. The image itself is built only by Build & Publish after a merge to dev, so #858 passed PR CI and then broke the dev publish. Build the builder stage in the PR job, as the shared matrix already does for profile-ui. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne-week fix: extend invitation links to one week
…test-fixtures fix(control-ui): keep test fixtures out of the image build context
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.
Promotes
devat27776e8→mainfor the second v0.12.0 prod deploy. Merge with a merge commit, not squash.v0.12.0 is not tagged yet. The tag goes on this PR's merge commit instead of
304766ab, so the release matches what prod will run. The release coordinates already say v0.12.0 from #1171 (releaseManifest.ts, the ghcr-images component, the desktop package), so this PR needs no version change.The head branch
chore/promote-v0.12.0-27776e8is fixed at dev27776e8ae, the tested head. Anything merged todevlater stays out of this promotion.What dev verified
sha-27776e8, recorded in infra commit53a3aad(run 40620574201).pin-status.yamlsaysverified: true.Included PRs
Deploy notes
charts/clerum-crds/**,deploy/**, database migrations, RBAC or ServiceAccounts. fix: extend invitation links to one week #1195 adds no migration: its two temporary migrations were removed before merge and never reached dev.sha-27776e8. That covers all Hosts: 14 running, plusoutreach-assistant, which is suspended.host_uid, so each Host gets one 401 and one renewal after the apply.replicas: 1withRecreate, whichdeploy/basesets and the prod overlay keeps.spec.oauth, so no OAuth grant changes behaviour.standalone.host_uidthat matches the live Host.product-statelessgets one workflow refresh 401 after each credential re-issue and recovers on the next one.CONTEXT_MAPPER_WORKSPACE_LAYOUT_MERGE="true"because infra#128 is not merged. The merge init runs again on every Host restart. It exited 0 on every Host at the Oct 26 deploy and again after the node replacement that evening.Follow-up
🤖 Generated with Claude Code
https://claude.ai/code/session_01Ua3JRtcTHSc4LDgPZNRnUf