groupNotPermitted telemetry cannot say which group was refused - report the resolved group identity from SQL
Raised by support-evolutiva-cc 2026-10-05 from telemetry, while the code was open rather than filed afterwards: the appEvents row for a groupNotPermitted refusal on POST /api/soporte/terra/usuarios proves that a group was refused and cannot say WHICH group was requested. That bites precisely because the whole point of the capability is granting a NON-admin group - the one question the row cannot answer is the one it exists to answer. IT CANNOT BE FIXED IN THE ROUTE, and that is the ruling, not a preference. The requested groupValue is caller-supplied free text, and appEvents is shared with terra under a >=365d retention floor with no retraction path, so the app may not copy it in. A shape allowlist does not rescue it either: 24 lowercase characters still hold a surname. The function is the only layer that can tell a real label from arbitrary caller text, because the vocabulary lives in `groups`. Asked of the db lane: extend fn_supportCreateTerraUser so a groupNotPermitted return reports the refused group's STABLE IDENTITY (its uuid, or its stored `value` read back from the row - a DB-held label, never the argument as received) when and only when the argument resolves to a real `groups` row, and reports nothing when it does not resolve. That also retires the collapse recorded on ENAMEL-69: today groupNotPermitted means EITHER a value outside the four-value allowlist OR an allowlisted group row that was renamed, deactivated or soft-deleted, and nothing downstream can separate the caller's mistake from our own drift. A resolved-vs-unresolved discriminator in the return separates them without duplicating the allowlist into app code. Shape it so the existing route keeps working unchanged: an added OUT column is a signature change, so per the overload trap it is a new function, not a modification - the ungated or stale old signature must not survive alongside it. Route-side logging of the new field, plus its test, is coder-enamel-cc's half and follows the APPLIED signature. Class-A on the same terms as enamel_078: design-ping, source review, forced-red of every acceptance control, exact-bytes GO from coder-enamel-cc. Same family as ENAMEL-64's presence-booleans residue.
Activity
-
parent=ENAMEL-69