You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent epics: #54 and #108. Split from the shared management-mask gap recorded in #245 and #250.
PM status — owner decision required
FAIL CLOSED. Do not engineer while decision and needs grooming remain.
Choose one default non-PII member label for every authorized private Studio/admin API course-registration, Enrollment, MemberProfile, operation, audit-safe presentation, and export surface. #245 and #250 must consume the same choice; neither may invent a separate email/name mask or reuse the event-provider helper.
This issue is only a product-presentation decision. It does not authorize a route, data read, export, mutation, schema change, production/provider access, or PII disclosure.
Normative authority and fixed invariants
_docs/specs/06-studio-and-admin-api.md requires deny-by-default function/object/field authorization, UUID management resources, masked support views, a separate full-PII capability, authorized-queryset-before-lookup behavior, private/no-store responses, and redacted audit evidence.
_docs/specs/07-security-privacy-operations.md makes MemberProfile private, requires non-enumerating safe failures, excludes profile values from analytics/observability, and keeps MemberProfile distinct from public content.Person.
_docs/specs/open-decisions.md resolves one private account-owned MemberProfile after verified ownership, independent of content.Person.
The only input is an already-authorized MemberProfile UUID. Email, normalized email, name, certificate/display alias, organization, profile values, content.Person, provider identifiers, and operator input are never inputs.
Parse the UUID, then canonicalize it as exactly 32 lowercase hexadecimal characters with hyphens removed. Invalid, absent, quarantined, colliding-identity, broken/cyclic/absorbed, inactive, deleted, unauthorized, and nonexistent subjects expose no label and preserve the consuming service's generic non-enumerating result.
The label is presentation only. The canonical full profile UUID remains the resource identity. A label is never accepted as a route identifier, lookup/search/filter key, idempotency key, authorization input, correlation key, or uniqueness proof.
A truncated-label collision never reveals PII, extends only one subject's label, changes the grammar dynamically, or changes denial behavior. Colliding labels remain identical; resource UUIDs and authorized object scope distinguish resources.
Labels are private, zero-TTL, no-store, noindex, absent from public pages/search/sitemaps/analytics. They do not grant PII access and do not widen the authorized queryset.
Ordinary application logs, metrics, traces, errors, job context, and provider payloads do not record the label. Append-only management audit may store the selected label only as its already-authorized redacted target-label snapshot beside target type/opaque UUID; denied/unknown targets receive no label. If the final audit registry is stricter, it stores the opaque UUID only—never a fallback email/name/digest.
HTML renders the exact literal text rather than CSS-only truncation. Its accessible name is Member identifier, starts <spaced prefix>, ends <spaced suffix> for truncated options, so the ellipsis and hexadecimal characters are not the sole spoken distinction. Labels remain text at zoom/reflow, are not color-only, and copy/links/actions keep a distinct accessible name. API and CSV serialize the exact visible string or null, never a different mask.
Exact candidate formats
Only the following existing-UUID formats are in this decision. They need no new identity input, persistent alias, or masking secret.
Option A — compact UUID edge label (recommended)
Member <first 4 hex>…<last 4 hex>
Use the literal prefix Member and one Unicode horizontal ellipsis … (U+2026), with no surrounding spaces. Example UUID 2f910000-0000-4000-8000-0000a1b2c3d4 renders:
Member 2f91…c3d4
Accessible name:
Member identifier, starts 2 f 9 1, ends c 3 d 4
Consequences:
exposes 32 bits of the already-authorized opaque UUID; stable for the lifetime of that profile and unaffected by email, name, profile-field, account-state, or course changes;
compact at mobile/reflow sizes and relatively short for screen-reader repetition;
truncated labels can collide. The UI/API/CSV must tolerate identical labels and retain the full authorized resource UUID separately; no adaptive suffix or PII fallback is allowed;
remains linkable across authorized private surfaces, so it is excluded from public output and ordinary observability despite containing no email/name characters.
Option B — extended UUID edge label
Member <first 6 hex>…<last 6 hex>
The same example renders:
Member 2f9100…b2c3d4
Accessible name:
Member identifier, starts 2 f 9 1 0 0, ends b 2 c 3 d 4
Consequences:
exposes 48 bits of the opaque UUID and is stable under the same conditions as Option A;
lowers accidental label-collision risk relative to Option A but still is not a uniqueness proof and retains exactly the same collision behavior;
is longer and more repetitive in dense tables, exports, zoom/reflow, and spoken output;
has greater cross-surface linkability than Option A and therefore retains the same private/no-store/logging restrictions.
Option C — full opaque UUID label
Member <canonical hyphenated lowercase UUID>
The same example renders:
Member 2f910000-0000-4000-8000-0000a1b2c3d4
Accessible name spells the UUID in its five canonical groups after Member identifier.
Consequences:
has no truncation collision beyond the authoritative resource identity and requires no second identifier beside the label;
exposes the complete stable opaque resource identifier and maximizes cross-surface linkability;
is cumbersome in tables, mobile layouts, CSV review, copying, and repeated screen-reader output;
is not recommended for the requested masked presentation, although it remains non-PII under current authority. It retains all private/no-store/logging restrictions.
Recommended safe default
Recommend Option A. It uses only the immutable authorized profile UUID, introduces no email/name disclosure, normalization policy, persistent alias, new secret, rotation lifecycle, or model field, and is the smallest consistent presentation across #245 and #250. Its collision tradeoff is acceptable only because the label is explicitly non-unique and never the resource or lookup key.
This is a recommendation, not approval.
Explicitly excluded formats
The following are not candidate defaults and require a new owner-reviewed decision if requested:
partial or hashed email, domain, name, certificate/display alias, profile text, or combinations of them;
the existing protected:<12 hex> helper, which is scoped to an external event-provider identifier and is not member-identity authority;
unkeyed hashes, reversible/encrypted values, stable recipient digests, or provider identifiers;
keyed/HMAC aliases, which would add secret ownership, rotation, versioning, historical audit/export behavior, and outage semantics not authorized here;
random stored aliases, which would add schema, uniqueness, migration, lifecycle, restoration, and deletion behavior not authorized here;
per-page ordinals or unstable masks, which cannot safely correlate list/detail/export/operation results;
any fallback from a missing/invalid/unauthorized profile UUID to PII or another identifier.
Downstream contract after owner approval
After an authorized owner selects an option and PM records it:
Add target-native course registration and enrollment reads and exports #245 uses one nullable member_label with the exact shared grammar for masked CourseRegistration and Enrollment Studio rows/details, admin API representations, operation summaries, and CSV columns. Its current default masked account identifier / masked normalized-email snapshot wording must be replaced rather than implemented alongside the shared label. Full account UUID/email remain separately capability-gated PII fields. Missing/unavailable labels serialize as null in API/CSV and display Hidden in Studio only where the consuming issue already distinguishes masked from genuinely absent data.
Add capability-scoped Member Studio and admin correction and Slack resend #250 uses the same nullable member_label for Members list/detail and safe correction/resend review/result presentation. The full authorized profile UUID remains the route/API resource ID. Full PII remains separately gated by accounts.member_profile.view_pii.
Shared operations and permitted audit target-label snapshots use the same grammar; adapters and exports may not fork it.
Both issues add collision fixtures, null/unavailable/non-enumerating fixtures, exact API/CSV/HTML parity assertions, redaction canaries, and desktop/mobile keyboard/screen-reader/zoom/reflow evidence. Approval of this label does not satisfy either issue's other dependency or lifecycle gates.
Until that reconciliation is complete, #245 and #250 remain decision / needs grooming; #246 may not finalize management result presentation before accepted #245.
Owner response required
An authorized product/security owner should reply with exactly one of:
APPROVE #288 OPTION A — COMPACT UUID EDGE LABEL
APPROVE #288 OPTION B — EXTENDED UUID EDGE LABEL
APPROVE #288 OPTION C — FULL OPAQUE UUID LABEL
or provide an exact replacement covering input, canonicalization, literal grammar, examples, collision behavior, missing/unavailable identities, stability/rotation, privacy/linkability, accessibility, logging/audit, and downstream API/CSV/HTML fields.
Decision acceptance and non-goals
An authorized owner response selects one exact format or supplies an equally complete replacement.
PM records the selected immutable grammar and consequences without weakening any invariant above.
Parent epics: #54 and #108. Split from the shared management-mask gap recorded in #245 and #250.
PM status — owner decision required
FAIL CLOSED. Do not engineer while
decisionandneeds groomingremain.Choose one default non-PII member label for every authorized private Studio/admin API course-registration, Enrollment, MemberProfile, operation, audit-safe presentation, and export surface. #245 and #250 must consume the same choice; neither may invent a separate email/name mask or reuse the event-provider helper.
This issue is only a product-presentation decision. It does not authorize a route, data read, export, mutation, schema change, production/provider access, or PII disclosure.
Normative authority and fixed invariants
_docs/specs/06-studio-and-admin-api.mdrequires deny-by-default function/object/field authorization, UUID management resources, masked support views, a separate full-PII capability, authorized-queryset-before-lookup behavior, private/no-store responses, and redacted audit evidence._docs/specs/07-security-privacy-operations.mdmakesMemberProfileprivate, requires non-enumerating safe failures, excludes profile values from analytics/observability, and keeps MemberProfile distinct from publiccontent.Person._docs/specs/open-decisions.mdresolves one private account-owned MemberProfile after verified ownership, independent ofcontent.Person.MemberProfileUUID: existing rows receive deterministic UUIDv5 values, later rows UUIDv4 values, and a stored UUID never changes. Build the accounts-owned MemberProfile schema and service foundation #247 is groomed but not yet accepted/integrated, so consumers remain dependency-blocked.Every option below retains these invariants:
MemberProfileUUID. Email, normalized email, name, certificate/display alias, organization, profile values,content.Person, provider identifiers, and operator input are never inputs.Member identifier, starts <spaced prefix>, ends <spaced suffix>for truncated options, so the ellipsis and hexadecimal characters are not the sole spoken distinction. Labels remain text at zoom/reflow, are not color-only, and copy/links/actions keep a distinct accessible name. API and CSV serialize the exact visible string ornull, never a different mask.Exact candidate formats
Only the following existing-UUID formats are in this decision. They need no new identity input, persistent alias, or masking secret.
Option A — compact UUID edge label (recommended)
Use the literal prefix
Memberand one Unicode horizontal ellipsis…(U+2026), with no surrounding spaces. Example UUID2f910000-0000-4000-8000-0000a1b2c3d4renders:Accessible name:
Consequences:
Option B — extended UUID edge label
The same example renders:
Accessible name:
Consequences:
Option C — full opaque UUID label
The same example renders:
Accessible name spells the UUID in its five canonical groups after
Member identifier.Consequences:
Recommended safe default
Recommend Option A. It uses only the immutable authorized profile UUID, introduces no email/name disclosure, normalization policy, persistent alias, new secret, rotation lifecycle, or model field, and is the smallest consistent presentation across #245 and #250. Its collision tradeoff is acceptable only because the label is explicitly non-unique and never the resource or lookup key.
This is a recommendation, not approval.
Explicitly excluded formats
The following are not candidate defaults and require a new owner-reviewed decision if requested:
protected:<12 hex>helper, which is scoped to an external event-provider identifier and is not member-identity authority;Downstream contract after owner approval
After an authorized owner selects an option and PM records it:
member_labelwith the exact shared grammar for masked CourseRegistration and Enrollment Studio rows/details, admin API representations, operation summaries, and CSV columns. Its current defaultmasked account identifier/masked normalized-email snapshotwording must be replaced rather than implemented alongside the shared label. Full account UUID/email remain separately capability-gated PII fields. Missing/unavailable labels serialize asnullin API/CSV and displayHiddenin Studio only where the consuming issue already distinguishes masked from genuinely absent data.member_labelfor Members list/detail and safe correction/resend review/result presentation. The full authorized profile UUID remains the route/API resource ID. Full PII remains separately gated byaccounts.member_profile.view_pii.Until that reconciliation is complete, #245 and #250 remain
decision/needs grooming; #246 may not finalize management result presentation before accepted #245.Owner response required
An authorized product/security owner should reply with exactly one of:
or provide an exact replacement covering input, canonicalization, literal grammar, examples, collision behavior, missing/unavailable identities, stability/rotation, privacy/linkability, accessibility, logging/audit, and downstream API/CSV/HTML fields.
Decision acceptance and non-goals
member_labelcontract, leaves their unrelated dependency gates intact, removes this issue's decision/grooming labels, and closes this decision issue only after that record is complete.Non-goals: implementing accounts/profile services; changing #247 identity/schema; permissions or PII capability work; course/member reads or exports; operation/audit infrastructure; support correction; Slack resend; privacy-rights workflows; routes/UI/API/OpenAPI; tests; migrations; deployment; production/provider/secret/data access; or changing public
content.Personbehavior.