Skip to content

[ruling row 7] the user bulk import must admit manager_id, resolved in a second pass keyed on the importer's identity key — split from #16678 #18028

Description

@os-project-manager

Maintainer-action: rule how a domain:services card obtains the CONTRACT_REVIEW_TIER clause-② verdict its carrier needs — route it to the spec seat (naming how), or rule that this seat's default-judgment-tier review plus the gates suffices — done when node scripts/pm/check-clause2-carriers.mjs --pair 18046 exits 0 with the carrier cleared on both carriers

Split from #16678's Phase 3 landing (5653051072), which flagged it in its own words:

⚠️ Ruling row 7 (admit manager_id to the bulk-import tier, resolved in a second pass keyed on email/phone) is ruled but not delivered hereadmin-import-users.ts is untouched and its 0-match reading still holds. That split is this seat's to carry, ⛔ not lost.

This is the card that carries it. The work is already ruled — ⛔ it does not go back to the decision box.

The ruling, verbatim

Ruling 5651634638 (director seat, decision batch #127 item 1, option B), §9 row 7:

7 Bulk importmanager_id admitted to the import tier, resolved in a second pass keyed on the importer's identity key (email / phone), every row-level refusal from row 2 applied, unresolved key = per-row error

Measured — the gap is still open

On origin/main @ 8261ff717:

reading result
packages/plugins/plugin-auth/src/admin-import-users.ts 632 lines
case-insensitive manager in that file 1 — and it is AuthManagerOptions in a comment, a word match, ⛔ not the field
⇒ field-level manager_id hits 0
POSITIVE CONTROL email in the same file 73

The control is what makes the zero a reading rather than a broken search.

⛔ Consume the landed endpoint; do NOT re-derive its refusals

Phase 3 landed packages/plugins/plugin-auth/src/admin-set-user-manager.ts (476 lines) and already exports the reusable parts:

:131  export const MAX_MANAGER_CHAIN_DEPTH = 20
:134  export type SetUserManagerRefusalReason =
        'self_assignment' | 'cycle' | 'max_depth_exceeded' | 'cross_organization' | 'idp_provisioned'
:146  export interface SetUserManagerEngine
:151  export interface SetUserManagerDeps
:165  export interface SetUserManagerResult
:333  export async function runSetUserManager(...)

The ruling says "every row-level refusal from row 2 applied". The file already carries that table, verbatim from its header:

refusal error status reason
self-assignment INVALID_FIELD 400 self_assignment
cycle RESOURCE_CONFLICT 409 cycle
depth cap VALUE_OUT_OF_RANGE 400 max_depth_exceeded
cross-organization INVALID_REFERENCE 400 cross_organization
directory-owned identity PERMISSION_DENIED 403 idp_provisioned

⇒ the second pass routes each row through the existing derivation. ⛔ A second copy of these five predicates in the importer is the drift this platform keeps paying for — it is the same shape as #15706 (a mirrored copy of auth rules) and the reason #16678's own design insisted on one derivation. If runSetUserManager cannot be called row-wise as it stands, say so with the measurement and propose the smallest seam; ⛔ do not fork the predicates.

What the card is

  1. Admit manager_id to the importer's accepted tier.
  2. Resolve it in a second pass, after all rows exist — the ruling's wording, and it is load-bearing: a manager named in row 40 may be created by row 90, so a single-pass resolve would refuse valid input.
  3. Key the resolve on the importer's identity key (email / phone) — the same key the importer already uses, ⛔ not a new one.
  4. Unresolved key ⇒ per-row error, not a whole-import failure and ⛔ not a silent skip.
  5. Apply every row-2 refusal per row, through the existing derivation.

Open questions the taker must answer with a measurement, not a guess

  1. Does the importer today have a place for a second pass at all, or does it commit row-by-row? That decides whether this is a small addition or a restructure — unmeasured here.
  2. What does the importer's existing per-row error channel look like (rows[].delivery is the shape its header mentions for delivery)? The per-row manager error should ride that channel rather than invent one.
  3. runSetUserManager's signature is written for one HTTP call with SetUserManagerDeps; whether N row-wise calls are acceptable or a batch seam is owed is a real design question — answer it with the file open.

Fences

Grading

Inherited from the parent: priority:p2, domain:services (landing site packages/plugins/plugin-auth). ⚠️ Triage may re-rank — the parent's p2 was set against the whole card, and this is its last row.

Refs

#16678 (parent, closed) · 5651634638 (the ruling) · 5653051072 (Phase 3 landing, which flagged this row) · #17995 (domain:spec, the error-vocabulary question for the same five refusals) · objectui#9361 (the Console affordance)


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions