mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
* feat(managed-agent): persist workspace actor roles and session owners
Slice B of #13535 (storage only, behavior-invisible):
- V48 migration replaces managed_workspace_access.can_read/can_create
with a single role column (READER/OPERATOR/OWNER, CHECK-enforced),
backfilling can_create -> OPERATOR and can_read-only -> READER, and
adds managed_agent_session.owner_actor_key backfilled from
creator_actor_key.
- WorkspaceAccess becomes NONE/READER/OPERATOR/OWNER (ordered, with an
atLeast helper); NONE remains the no-row decision, never storable.
- Every grant reader (canRead, findReadable, listReadable,
readableDefault, resolveForCreation, authorizePassiveAttachment, the
cwd-change registry-facts join, the listSessions EXISTS filter) keeps
its current truth table, re-derived from role.
- insertSession writes owner_actor_key = creator on both bound and
legacy creation paths; anonymous legacy creation leaves both NULL.
- Test fixtures move to the role column; revocations that previously
zeroed booleans now delete the grant row (the honest no-access
equivalent under the CHECK); a (FALSE,TRUE) fixture state that role
ordering makes unrepresentable becomes a grant-row deletion.
- New tests: V47->V48 migration shape (backfill, owner:=creator, CHECK
rejects NONE/invalid, post-V48 store-path creation writes owner) and
session-owner store test (bound/legacy owner write, anonymous NULL).
The full managed-agent-server suite differs from baseline only in the
new tests; ManagedSessionStoreIntegrationTest#holdsRestorePages
InsideThePerPageByteBudget errors identically on unmodified HEAD
(verified in a clean worktree at ac497aeed9).
* fix(managed-agent): drop unreadable workspace grants before the V48 backfill
A (can_read=FALSE) row grants nothing under the booleans, but the role relabel would have given it READER (or OPERATOR with can_create). Dropping such rows keeps the migration a pure relabel for every reachable grant; pins the drop for (FALSE,TRUE) and (FALSE,FALSE) shapes in the migration test.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(managed-agent): renumber roles migration to V51 and drop its default
#13260 took V48-V50 while this branch sat in review; the roles
migration therefore renumbers to V51. W1c's chain never touches
managed_workspace_access or managed_agent_session, so the renumber is
a pure rename for its backfill targets.
The triage finding on #13544 also lands: role drops its 'READER'
default so an INSERT omitting it fails loudly (violates NOT NULL), as
omitting a boolean did. The column arrives NULL, the backfill fills
every existing row, and MODIFY COLUMN tightens it to NOT NULL right
after — H2 cannot backfill a no-default NOT NULL ADD COLUMN on a
non-empty table.
Reconcile main-side fixtures added by #13543 and #13260 against the
old boolean columns (SurfaceAdmissionAcceptanceTest grant helper and
artifact fixture, ManagedAgentApiContractTest migration-refusal
fixture, ManagedActionsTest migration-fence fixture,
WorkspaceMigrationMySqlIT admission fixtures): TRUE/TRUE -> OPERATOR,
TRUE/FALSE -> READER; no admission-family assertion changes.
ManagedWorkspaceRolesMigrationTest pins the omission-fails behaviour,
and the design docs quote the new SQL shape in both languages.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(managed-agent): reconcile mysql-profile ITs with the V51 shape
The mysql-integration profile runs history-seeded suites the H2 gate
cannot see, and the MariaDB lane caught two:
- WorkspaceSessionRetentionMySqlIT seeds its grant row at V31, where
the columns are still the booleans; the slice-B role INSERT is
grammar-invalid there. The seed returns to (TRUE, TRUE), which the
V51 backfill maps to OPERATOR on upgrade — downgrade-path
assertions unchanged.
- WorkspaceMigrationMySqlIT pins the post-V47 versions W1c adds as
exactly 48-50; V51 is the fourth in this tree, so the
contains-exactly list gains "51".
Verified against a local MariaDB 10.11.19 (the lane runs 10.11.18):
WorkspaceMigrationMySqlIT 5/5 and WorkspaceSessionRetentionMySqlIT
16/16 under -Pmysql-integration verify, BUILD SUCCESS.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(managed-agent): move the failover E2E fixture to the role column
run-managed-agent-server-e2e.ts seeds the bound-session workspace
grant with the boolean columns; once the schema migrates to V51 the
INSERT dies with ERROR 1054 (unknown column 'can_read') and every
failover scenario in the hosted MySQL lane fails before the fixture
spins up. The grant maps to OPERATOR, matching the (TRUE, TRUE)
booleans it replaces and the backfill's relabel.
Co-authored-by: Qwen-Coder <[email protected]>
* fix(managed-agent): make the role CHECK byte-exact and unmask its tests
Review on #13544 found two gaps in V51's stored guarantee, both real
on their evidence and verified independently here:
- utf8mb4 comparisons are PAD SPACE, so the IN-list CHECK accepted and
preserved 'READER ' — a value every WorkspaceAccess.valueOf reader
rejects, so one out-of-band provisioning slip turns an actor's
discovery routes into 400s. The CHECK now pairs each name with its
exact length ('READER' = 6, 'OPERATOR' = 8, 'OWNER' = 5). An
anchored REGEXP solves the padding too, but its backslash arrives
rewritten on MySQL (string literals escape it, H2's do not), so the
predicate deliberately carries none; H2 2.4.240 and MariaDB 10.11.19
both prove it accepts exactly the three canonical names and rejects
padded, lowercase and unknown values.
- The negative migration assertions reused the seeded OPERATOR actor
key, so each collided on the primary key and DuplicateKeyException
(a DataIntegrityViolationException) satisfied them regardless of
the CHECK's presence or the role default's absence. Every negative
case gets a fresh, unseeded actor key, and the padded-value case
joins the set so the byte-exactness regression is pinned in H2.
ManagedWorkspaceRolesMySqlIT carries the same matrix on a real engine
in CI (canonical stored untouched, padded and unknown rejected with
nothing persisted).
Co-authored-by: Qwen-Coder <[email protected]>
* fix(managed-agent): renumber the roles migration to V52 and move L3 test grants to role
L3 (#13354) took V51 for workspace_session_lifecycle, colliding with this branch's roles migration at merge time (the merged jar failed startup on a duplicate version 51). The roles migration becomes V52; the design docs (EN and zh-CN), the roles migration-shape and retention tests, and WorkspaceMigrationMySqlIT's post-V47 pin (now 48-52) follow. The grants L3's tests still write as booleans move to role with the semantics the storage keeps: fixture INSERTs seed OPERATOR, the create-flip updates use READER/OPERATOR, and the revoke-by-boolean case becomes the delete role semantics make of it.
Locally the Flyway uniqueness gate passes (52 migrations, unique) and the full managed-agent-server H2 suite runs 1370/0/0, the same count the real-stack run reported with 54 merge-shaped errors.
* fix(managed-agent): renumber the roles migration to V53 and reconcile #13163's fixtures
#13163 took V52 for the mutation-attempt sequence while this branch
carried V52 for the roles migration; the roles migration moves to V53.
#13163's own test fixtures still write the dropped boolean columns and
now sit on the V53 schema, so they move to the shapes the storage keeps:
the StorageGuard revoke/restore flips use READER/OPERATOR, the
cold-cancel mutability ladder uses OPERATOR/READER and turns its
lose-read case into the grant-row deletion, the admission scenario's
create-revoke uses READER, and WorkspaceMigrationMySqlIT pins the
post-V47 versions as 48-53.
Locally the flyway gate passes (53 migrations, all versions unique), the
full managed-agent-server H2 suite runs 1394/0/0, and the four key
integration suites run 27/0/0 on MariaDB 10.11.19 (Roles, Migration,
Retention, Close).
Co-authored-by: Qwen-Coder <[email protected]>
* fix(managed-agent): make the roles IT portable across engines and drop its schema
The real-engine verification round on #13544 found three test-side
items in the new ManagedWorkspaceRolesMySqlIT. The CHECK-violation
shape reaches the runtime as different Spring exceptions per engine —
MySQL 8.4 reports 3819/HY000, which Spring 6.2 cannot map, so it
surfaces as UncategorizedSQLException while MariaDB's 4025/23000 maps
to DataIntegrityViolationException — and the negative matrix asserted
the latter, failing any MySQL run. The assertion now talks
DataAccessException plus the constraint name, matching the engines the
slice runs on and keeping the mutation coverage mutants cannot dodge.
The class javadoc and the H2-side comment now name the shipped
length-guarded CHECK instead of the shape's earlier REGEXP phrasing,
and the class drops its per-test schema like its neighbouring ITs.
Verified on MariaDB (fresh schema per run, 1/1) and H2 (migration test).
Co-authored-by: Qwen-Coder <[email protected]>
---------
Co-authored-by: Qwen-Coder <[email protected]>