Skip to main content

RFC Review: Enable Team Owner Field & Team Permission in CDP

Companion review for rfc-team-owner-field-and-team-permission.md, produced by the rfc-reviewer skill. Cumulative across cycles R1 → R2; valid for the RFC revision in reviewed_commit (dce8b7d).

Executive Summary

  • Overall Score: 8.5/10 (was 6.5 at R1)
  • Rating: Agentic-Ready (was Needs Work)
  • RFC Type: full-stack
  • Sub-Type: new-feature (frontend) + new-feature (backend)
  • Assessment Confidence: High
  • Applied Caps/Gates: none — the R1 cross-layer-contract cap (6.5) is lifted: the teams-for-user contract is now pinned normatively in §2.4 and Detail 2.G is all-yes. ACV ≥ 5.0; deploy order specified; OBS cap cleared (FE analytics added); 0 categories below 5.0.
  • Implementation Readiness Verdict: PROCEED — with one delivery note: GA waits on Launchpad shipping the §2.4 teams-for-user endpoint + the Team Only radio (CHG-001). That is a build dependency, not an agent-blocking spec gap; all in-repo chunks (BE 1–7, FE 8–9, Mobile 10) are executable now.
  • Report Path: cdp/team-owner-field-and-team-permission/rfcs/rfc-team-owner-field-and-team-permission-review.md
  • RFC Author: Zhelia Alifa | Reviewed: 2026-06-18 (R2)

R2 confirms every R1 finding (REV-1..8) is resolved. The decisive change is REV-1: the teams-for-user(+descendants) contract is now an authoritative spec in §2.4 (path, params, full 200 schema, error/empty/timeout semantics, caching) that both the CDP consumer and the FE picker build against — so the cross-layer ambiguity that capped the RFC at 6.5 is gone and Detail 2.G reads all-yes. The dangling decisions also closed: descendants expand in Launchpad (OQ-3a), notes broadening confirmed and flag-gated (OQ-11), and the migration is a CDP-owned backfill job (OQ-1). The one honest residual is that Launchpad must still deliver the endpoint it's been handed a contract for — tracked as REV-9 (accepted-risk), and correctly gated behind cdp_team_permission_enabled = OFF. An agent can implement both layers from this RFC without a clarification meeting.


Quick Verdict

Why this RFC can be implemented agentically:

  • The previously-missing dependency contract is now fully pinned (§2.4): an agent writes the CDP HTTP client + cache and the FE getMyTeams() against one agreed shape — no field-name guessing.
  • All major decisions are closed (10 ADR blocks + the 3 ex-open ones now resolved); backend authorization is specified to file:line with a single evaluation authority.
  • 11-chunk execution plan with repo-sourced commands and assertable AC; clean cross-layer rollout matrix; flag kill-switch.

Why an agent might still pause (notes, not blockers):

  • The teams-for-user endpoint is RFC-defined but not yet Launchpad-ratified/shipped (REV-9, accepted-risk) — in-repo chunks proceed against the contract/a stub; end-to-end GA waits on delivery.
  • Backend perf baseline numbers are intentionally "measure before build" (REV-6 resolution) rather than pre-stated absolutes — correct for an unmeasured tenant, but the agent must capture them, not invent them.

Findings Ledger (carry-forward)

R1 ids carried forward, statuses updated. 0 open material findings after R2; one new accepted-risk (REV-9) tracks the external delivery dependency.

IDSeverityFinding (one line)RFC locationStatusFirst seenResolved inEvidence / fix
REV-1blockerTeams-for-user(+descendants) contract proposed, not agreed§2.4 Dependency endpoint, Detail 2.GfixedR1R2 / dce8b7d§2.4 now pins normative contract (path, 200 schema, errors, empty, 500ms timeout, cache key); Detail 2.G flipped to all-yes. Residual delivery → REV-9
REV-2majorFigma frames TBD for all surfaces§1 Design ReferencesfixedR1R2 / dce8b7dDeclared no net-new visual — every CDP FE surface is a pixel-faithful reuse (fork of MultipleSelect.vue; sidebar clone); gate cleared, not deferred
REV-3majorNotes update/delete broadening unconfirmedDecision 8, OQ-11fixedR1R2 / dce8b7dOQ-11 resolved = yes (flag-gated); Decision 8 + Stories 14/16 encode it
REV-4majorMigration ownership unresolvedCHG-004, OQ-1, ch 11fixedR1R2 / dce8b7dChosen: CDP-owned backfill job (not Bifrost), with rationale + reversibility in §4 Rollout
REV-5minorLevel-update path differs from PRD; gateway unconfirmed§1 Deps, Detail 2.F.1fixedR1R2 / dce8b7dDocumented no CDP impact (CDP reads crs_permissions; admin UI Launchpad-owned); closed for this RFC
REV-6minorNo throughput / cache / load-test numbers§3 PerformancefixedR1R2 / dce8b7dAdded: no-new-RPS reasoning, ≥95% cache-hit assumption, 500ms client timeout, pooled client, 1×/2× load test + cold-cache + degraded-Launchpad runs (baseline to be measured)
REV-7minorFE analytics events absent§3 MonitoringfixedR1R2 / dce8b7dAdded 4 FE analytics events with properties; OBS cap lifted
REV-8minorBrowser support matrix not stated§3 Performance (FE)fixedR1R2 / dce8b7dStated: inherits existing qontak-customer-fe matrix; no new constraint
REV-9minorteams-for-user endpoint RFC-defined but not yet Launchpad-ratified/shipped§1 Deps, §2.4accepted-riskR2Correctly gated behind cdp_team_permission_enabled = OFF; in-repo chunks proceed against the pinned contract. Delivery + ratification is a Launchpad checkpoint, not a CDP spec gap

Ledger summary: 0 open, 8 fixed this cycle (R1→R2), 1 accepted-risk (REV-9). No material finding remains to promote into the RFC Open-Questions table; REV-9 is mirrored in the RFC §5 "External delivery dependencies" block.


PRD → RFC Traceability Matrix

PRD ElementRFC SectionCoverage
CHG-001 Team Only radio (Launchpad)TEAM-S01, §1 Deps, Detail 2.F.1Full (cross-squad, no CDP impact — REV-5)
CHG-002 Enforce TEAM ONLY (4 actions)Decisions 1/2/5/7, §2.4, ch 2–6Full
CHG-003 Team Owner fieldDecision 3, §2.3, §2.A, ch 1/8Full
CHG-004 MigrationCHG-004 → Detail 2.F, ch 11Full (was Partial — owner now CDP job, REV-4)
CHG-005 Dedicated flagDecision 9, §4Full
CHG-006 Notes TEAM ONLYDecision 8, §2.4 notes, ch 7Full (OQ-11 resolved, REV-3)
FE-1..6 / MB-1..2Detail 1.C, §2.0 anchorsFull
Stories 1–17 (AC)Detail 1.A + 1.CFull — 17/17
§6.5 Observability§3 Monitoring (BE events + FE analytics)Full (FE added, REV-7)
Hierarchy/Unassigned (D-2/7/13)Decision 2, §2.2Full
Teams-for-user dependency (§7)§2.4 (pinned), §1 DepsFull (was Partial — contract pinned, REV-1)

Summary: 13 of 13 PRD elements fully covered (was 11/13 at R1). 0 RFC decisions without a PRD driver.


Scorecard

Full-Stack Scorecard (18 categories) — R2 (Δ vs R1)

#CategorySourceScoreΔEvidence-Based Rationale
1PRT — PRD TraceabilityMerged9.0=13/13 full; forward+reverse + 17/17 stories in Detail 1.C
2TDC — Technical DecisionsMerged9.0+0.510 ADR blocks; the 3 ex-open decisions (OQ-3a/OQ-1/OQ-11) now resolved with rationale
3CNT — Contract SpecificityFE8.0+0.5TeamOwnerSelectProps typed + emit ids; pixel-faithful reuse declared (no net-new design gap)
4SCB — Scope BoundariesFE9.0=Detail 2.I create/modify/NOT-touched; component forked not edited
5DEP — DependenciesFE8.5+0.5teams-for-user now contract-defined (still needs-building, but spec'd)
6NFS — Non-FunctionalFE8.0+1.0a11y + perf + browser matrix now stated (REV-8)
7TPS — Test PlanFE8.0=repo-sourced commands; cross-layer row
8DMS — Data Model & SchemaBE8.5=JSON migration 033 up/down, multikey index, cardinality, PII, examples
9ACV — API ContractBE8.5+2.0CDP endpoints fully tabled plus the dependency endpoint now fully specified (schema, errors, empty, timeout, caching) — REV-1
10DIC — Data IntegrityBE8.0=single-doc strong consistency; idempotent backfill
11FMC — Failure ModeMerged8.5=fallback-to-OWNED + 403/422 catalog + FE error catalog; codes match
12CSS — Concurrency & ScalingBE8.0+1.0throughput model + ≥95% cache-hit + 500ms timeout + load-test plan (REV-6)
13SAS — Security & AuthorizationBE9.0=Role × Endpoint matrix; per-element 422; injection/SSRF/tenancy; staticcheck
14ROL — Rollout & RollbackMerged9.0+0.5deploy order; clean compat matrix; flag kill-switch; migration owner = CDP (REV-4)
15OBS — ObservabilityMerged8.5+1.5BE 4 events + alerts and FE 4 analytics events (REV-7) — cap lifted
16SBC — Service BoundaryBE8.5=sync path, no new queue, routes reused/extended, Launchpad boundary explicit
17CPA — Pattern AlignmentMerged9.0=FE + BE patterns cited per concern; snake_case both sides
18CDG — ComplianceBEN/A=new field is non-PII; contact-PII handling unchanged

Overall (judgment): 8.5 — Agentic-Ready. Held just at the floor of the top band (not higher) because CNT and DIC sit at 8.0 (< 8.5), so the "9.0+ requires ACV/DIC/FMC/CNT all ≥ 8.5" gate isn't met — and REV-9 (un-shipped dependency) is a real, if non-blocking, operational risk.

Resource & Cost Advisory

  • Unchanged: no new pods; +1 cached Launchpad call/viewer/TTL; one small multikey index. Advisory only.

Decision Closure Assessment

Decision Index (R2)

#DecisionStatus R1 → R2Notes
1Scope on stored team_owner_idsResolved → Resolved
2TEAM ONLY rule + fail-to-OWNEDResolved → Resolved
3Multi-select, emit idsResolved → Resolvedno net-new visual (REV-2)
4Expand descendants in LaunchpadPartial → ResolvedOQ-3a closed; §2.4 returns expanded_team_ids
5$in via bson:"-" fieldResolved → Resolved
6Multikey index 033Resolved → Resolved
7Extend EvaluatePermissionsResolved → Resolved
8Notes inherit parent scopePartial → ResolvedOQ-11 confirmed (flag-gated broadening)
9Dedicated flag (default OFF)Resolved → ResolvedOQ-8 single-bool default, non-blocking
10Picker from user's own teamsPartial → Resolvedsource = pinned teams-for-user teams[]
Migration ownershipDangling → ResolvedCDP backfill job (REV-4)

Aggregate: 11 of 11 Resolved (was 7 Resolved / 3 Partial / 1 Dangling at R1). No dangling decisions remain.


Cross-Layer Contract Verification (R2)

EndpointBackend ResponseFrontend ExpectedMatch?Gaps
GET /cdp/customers*Contact{…, team_owner_ids:[]string}Contact{…, team_owner_ids?: string[]}Yes
PATCH /cdp/customers/{id}accepts team_owner_ids, 422sends ids, handles 422 revertYes
notes list/getNote{…, permission:{update,delete}}web note.permission.*; mobile NoteCdpPermissionResponseYesmobile extends gating to add/edit (ch 10)
teams-for-user (LP→CDP){data:{team_ids, expanded_team_ids, teams[]}} (§2.4, pinned)CDP expanded_team_ids; FE teams[]Yescontract pinned; Launchpad delivery = REV-9

Mismatches found: 0 (was 1 at R1). No cap applies.


Cross-Layer Rollout Compatibility Matrix

Unchanged from R1 — all scenarios Yes, deploy order BE→FE (mobile independent, flag last), 0 incompatible scenarios. Migration owner now named (CDP).


Strengths

  • REV-1 fully closed at the spec level (§2.4). The dependency contract is now authoritative — path GET /private/users/{user_sso_id}/teams?include_descendants=true, full 200 schema with team_ids/expanded_team_ids/teams[], explicit empty-array-for-teamless, 401/404/500 + 500ms-timeout→fallback semantics, and the (company,user) cache key. This is the single change that lifts the RFC from HOLD to PROCEED.
  • All decisions closed (11/11). Descendant expansion, notes broadening, and migration ownership — the three soft spots at R1 — now have explicit decisions with rationale and reversibility.
  • Honesty preserved. The author didn't paper over the residual: Launchpad delivery is tracked as REV-9 (accepted-risk) and the feature is correctly dark behind cdp_team_permission_enabled = OFF.

Biggest Gaps (now minor)

  • REV-9 (accepted-risk) — Launchpad must still build the endpoint to the §2.4 contract; until then GA is blocked (but in-repo execution is not).
  • REV-6 residual — backend perf baseline is "measure before build"; an agent must capture the everything P95/RPS, not assume them.
  • CNT/DIC at 8.0 — both solid; reaching 9.0+ overall would need e.g. a typed FE 422-handling contract example and an explicit duplicate-write note — polish, not blockers.

Priority Actions (post-PROCEED, for GA)

  1. Launchpad — implement GET /private/users/{user_sso_id}/teams?include_descendants=true to the §2.4 schema; ratify the shape (REV-9) and ship the Team Only radio (CHG-001).
  2. CDP — capture the everything list P95 + RPS baseline before enabling the flag (REV-6), so the ≤2s/≤20% targets are measurable.
  3. CDP — run the migration backfill (chunk 11) + the cold-cache and Launchpad-degraded load runs on a QA tenant before per-tenant enable.

Implementation Readiness Checklist

Unblocked (agent can proceed)

  • PRD → RFC traceability complete (13/13 full)
  • All technical decisions resolved (11/11; 0 dangling)
  • Failure modes handled + error catalogs (Detail 3.A/3.B/3.C)
  • Configuration contract: flag + cache TTL + Launchpad config
  • Rollout plan + clean cross-layer matrix + migration owner (CDP)
  • Observability: BE events + alerts and FE analytics events
  • Task decomposition with verifiable AC per chunk
  • FE interfaces/prop types + 5-state UI matrix; no net-new visual gate
  • Browser matrix stated
  • Cross-layer contract verified — all rows Yes
  • Deploy order specified; feature-flag coordination defined
  • End-to-end data flow documented
  • Schema at DDL/index precision; transaction boundaries; injection/tenancy

Blocked (must fix before GA, not before agent execution)

  • REV-9 Launchpad delivers + ratifies the §2.4 teams-for-user endpoint and ships the Team Only radio

Verdict: Ready to implement (in-repo) — GA gated only on the named Launchpad delivery (REV-9).


Task Manifest

Unchanged from the RFC's Detail 4.D (11 chunks, verified well-formed and dependency-ordered). Chunk 11 (backfill) is now concretely scoped as a CDP-owned job. No re-derivation needed.


Dangling Decisions Log

#DecisionLocationStatus
(none)All 11 decisions Resolved as of R2

Open Questions

#QuestionCategorySeverity
1Will Launchpad implement + ratify the §2.4 teams-for-user contract and ship CHG-001 on the GA timeline? (REV-9)DEP / SBCImportant (GA gate, not exec gate)
2Capture everything list P95/RPS baseline before flag-on (REV-6 residual)?CSSNice-to-have

Prior R1 open questions REV-1..8 are all closed (see Findings Ledger).


Evidence Notes

  • §2.4 Dependency endpoint — the pinned contract is the pivotal R2 evidence; drove ACV +2.0 and lifted the cross-layer cap.
  • Decisions 4 & 8 + §4 Rollout — explicit resolutions of OQ-3a / OQ-11 / OQ-1 drove TDC/ROL up and emptied the dangling-decisions log.
  • §3 Performance + Monitoring — added throughput/cache/load-test (CSS) and FE analytics (OBS cap lifted).
  • §1 Design References — "no net-new visual" reframing cleared the CNT design gate honestly (reuse, not imagined frames).

Review History

CycleDateReviewed RFC revisionScoreVerdictFindings open → fixedNotes
R12026-06-18last_updated: 2026-06-18 / 169a7da6.5HOLD8 open (1B/3M/4m)First review. Held to "Needs Work" by the unfinalized teams-for-user contract (REV-1) + pending design (REV-2).
R22026-06-18last_updated: 2026-06-18 / dce8b7d8.5PROCEED8 fixed, 1 new accepted-risk (REV-9)All R1 findings resolved: §2.4 contract pinned (cap lifted), 11/11 decisions closed, no net-new visuals, FE analytics + perf + browser matrix added. Residual = Launchpad delivery (REV-9), correctly flag-gated. Score 6.5 → 8.5.
R2*2026-06-18last_updated: 2026-06-18 / c8748288.5PROCEEDno changeRe-stamp only: Launchpad anchor re-verified on the canonical checkout (Documents/works/qontak-launchpad, main @ 20a3063) — level-update is rest_router.go:172 (not :154 from a stale clone), /private prefix confirmed. Citation fix; no finding/score change.