basquetWi + New ticket
terra TERRA-175

Quien ve la PAGINA DE GESTION del catalogo de cirugias: CATALOG_ROLES gatea solo /cirugias y su estado de confirmacion, mientras el picker de practicas lee las mismas cirugias por PRACTICA_ROLES

Done normal ctcoder02-terra-cc

La fuente declara que la lista CATALOG_ROLES ES la unica decision abierta de la catedra, y ningun row la tenia. src/lib/route-access.ts:62-66, textual: "client first because the cirugias catalog is the reason that role can log in at all today: the catedra's one open decision IS that list. admin and bedel reach it too - the confirmation state is an operational fact, not a client-only one." Debajo, CATALOG_ROLES = ["client","docente","jtp","bedel","admin"]. QUE ESTA VIGENTE HOY, leido de la fuente y no del comentario: cinco de los seis roles sembrados leen el catalogo de cirugias - todos menos alumno. Y no es solo navegacion: src/app/cirugias/page.tsx:81-90 confirma que la lectura y la confirmacion son limites distintos en la misma pagina, o sea que LEER es mas ancho que CONFIRMAR. La pregunta abierta es quien puede LEER, que es la que nadie tiene asignada. POR QUE NECESITA ROW PROPIO Y NO ES UNA ENMIENDA A NINGUNO DE LOS TRES QUE PARECEN CUBRIRLO. TERRA-150 decide quien puede CREAR una practica. TERRA-149 decide quien puede ATRIBUIR un ayudante nombrado. TERRA-143 decide que campos del formulario se adoptan y cuales ausencias son deliberadas. Ninguno toca la admision de lectura al catalogo. Un lector del backlog que busque "quien ve las cirugias" encuentra esos tres y concluye que esta cubierto - que es exactamente el modo de falla que TERRA-150 documento cuando se filo por la misma razon. LO QUE HACE ESTO DISTINTO DE LOS OTROS TRES, y es la razon por la que vale la pena filarlo aparte: client es el unico rol cuya EXISTENCIA depende de esta lista. El comentario lo dice sin rodeos - el catalogo de cirugias es la razon por la que ese rol puede iniciar sesion. Estrechar CATALOG_ROLES no le saca una pantalla a client, le saca la unica que tiene, y con ella el motivo de la cuenta. Cualquier decision que lo excluya es en los hechos una decision sobre si el rol client sigue existiendo, y quien la tome tiene que saberlo. NO ES UN DEFECTO Y NO SE DEBE ARREGLAR. El default vigente es coherente y falla cerrado para roles futuros: un rol sembrado el ano que viene no hereda la lectura por no estar en la lista. Falta el fallo sobre los cinco actuales, no un fix. CONDICION DE CIERRE, para que no termine en otro comentario: o se confirma el conjunto actual de cinco, o se define uno mas angosto; despues pagina y accion quedan consistentes con el fallo; y despues la frase de route-access.ts:62-66 que dice que esa lista ES la decision abierta la BORRA el commit que ship el fallo. Mientras ese comentario siga ahi, esta diciendo en voz alta que lo de abajo no es un fallo. Provenance: encontrado por coder-terra-ca en una auditoria backlog-contra-fuente acotada, 2026-09-01, con cobertura declarada de solo lectura de fuente - sin browser, sin base, sin Vercel, sin tests, y excluyendo el trabajo de TERRA-144 que ese mismo lane escribio esta sesion. No lo file por su palabra: lei route-access.ts:58-70 yo mismo y las dos citas son textuales.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 6w ago
  • wi-cli-venus audit-finding · 6w ago
    CORRIJO EL TITULO Y EL ALCANCE DE ESTE ROW, QUE YO MISMO FILE HACE MEDIA HORA. La decision abierta existe, pero NO es "quien puede LEER el catalogo de cirugias". Es mas angosta, y la diferencia cambia quien queda afectado. LO QUE MEDI AHORA, con grep sobre src/ en vez de leer el comentario: CATALOG_ROLES se usa en UN SOLO lugar de toda la aplicacion, src/app/cirugias/page.tsx:81. No gatea ningun otro archivo, ninguna action y ningun fetch. Y EL DATO TIENE UN SEGUNDO LECTOR CON OTRA PUERTA. src/app/practicas/nueva/page.tsx gatea en PRACTICA_ROLES (:33) y despues llama getCirugias() dentro de su Promise.all (:39). Osea que un alumno, que NO esta en CATALOG_ROLES, SI obtiene la lista de cirugias - como picker, para elegir una al cargar una practica. Tiene que poder: cirugiaId es NOT NULL en terraPracticas, asi que sin leer esa lista no hay practica posible. ENTONCES LA LECTURA DEL CATALOGO NO ESTA RESTRINGIDA A CINCO ROLES. Esta disponible para los cinco de PRACTICA_ROLES por el picker, y ADEMAS la pagina /cirugias esta disponible para los cinco de CATALOG_ROLES. Son dos conjuntos distintos sobre el mismo dato, cada uno con su propia puerta, y ninguno es un subconjunto obvio del otro - alumno tiene picker sin pagina, client tiene pagina sin picker. LO QUE CATALOG_ROLES REALMENTE GOBIERNA es el acceso a la pagina de GESTION del catalogo: la que muestra el estado de confirmacion por cirugia y donde se renderizan los controles de confirmar y retirar. Y esos dos ya estan gateados por separado y mas angosto, leido en la misma pagina: canConfirm sale de CLIENT_ROLES (:89) y canRetire de RETIRE_ROLES_SQL (:98), con un comentario que explica por que no reusa ADMIN_ROLES. La propia pagina dice "READING IS WIDER THAN CONFIRMING" y "RETIRING IS NARROWER THAN CONFIRMING, which is narrower than reading" - tres niveles, no dos. LA PREGUNTA ABIERTA, REFORMULADA: quien debe VER LA PAGINA DE GESTION del catalogo, o sea quien debe ver el ESTADO DE CONFIRMACION de cada cirugia. No quien puede ver los nombres de las cirugias, que ya lo puede todo el que carga una practica. QUE SIGUE EN PIE DEL HALLAZGO ORIGINAL, y es la parte que valia el row: la frase de route-access.ts:62-66 que declara que esa lista ES la unica decision abierta de la catedra sigue ahi y sigue sin tener dueno, y el rol client sigue dependiendo de esa lista para existir - /cirugias es su unica pantalla, asi que estrecharla lo deja sin motivo de cuenta. Eso no cambia. Lo que cambia es que excluir a alguien de CATALOG_ROLES no le saca la capacidad de ver que cirugias hay. COMO ME EQUIVOQUE, porque es la misma clase que ya me paso esta noche con TERRA-136: verifique la CITA y no el ALCANCE. Lei route-access.ts:58-70 yo mismo y confirme que las dos citas de coder-terra-ca eran textuales, y las eran. Lo que no hice fue preguntar si ese constante es el unico camino al dato, que es una consulta de grep de treinta segundos. Un nombre como CATALOG_ROLES sugiere que gobierna el catalogo; gobierna UNA PAGINA, y el catalogo tiene otro lector. Confirmar que un comentario dice lo que dice no es confirmar que lo que dice sea el alcance completo. CONDICION DE CIERRE, actualizada: o se confirma el conjunto actual de cinco para la pagina de gestion, o se define uno mas angosto; despues la pagina queda consistente con el fallo; y despues se BORRA la frase de route-access.ts:62-66 que declara la decision abierta, en el mismo commit. Mientras ese comentario siga ahi esta diciendo que lo de abajo no es un fallo. El picker de /practicas/nueva NO forma parte de esta decision: quien puede cargar una practica es TERRA-150 y se pregunto en eq 67.
  • wi-cli-venus titleChanged · 6w ago
    Quien ve la PAGINA DE GESTION del catalogo de cirugias: CATALOG_ROLES gatea solo /cirugias y su estado de confirmacion, mientras el picker de practicas lee las mismas cirugias por PRACTICA_ROLES
  • wi-cli-venus audit-finding · 6w ago
    CENSO COMPLETO DE CAMINOS DE LECTURA AL CATALOGO, hecho por coder-terra-ca. Confirma que mi propia formulacion de este row era falsa por alcance, y da el numero que faltaba: NO son dos puertas, son DIEZ. EL NUMERO. Dos primitivas de gate (requireAppUserPage y requireAppUserAction), OCHO constantes de rol distintas sobre estos caminos - PRACTICA_ROLES, ROSTER_ROLES, INFORME_ROLES, CATALOG_ROLES, CLIENT_ROLES, ADMIN_ROLES, RETIRE_ROLES_SQL, mas un caso SIN constante nombrada - y diez combinaciones distintas de gate mas constante si se cuentan por separado las formas page y action. PRACTICA_ROLES y CLIENT_ROLES aparecen en las dos formas. Las puertas, cada una con su gate: /practicas/nueva:33 PRACTICA_ROLES (quince lectores del catalogo detras de ese solo gate, :37-61), /practicas:87 ROSTER_ROLES, /informes:67 INFORME_ROLES, /practicas/[id]:64 PRACTICA_ROLES mas PRACTICA_ACCESS_SQL adentro del SQL en practica-detail.ts:243, /mi-perfil:30 requireAppUserPage() SIN constante - solo membresia, /cirugias:81 CATALOG_ROLES, /panel:39 CLIENT_ROLES, /administrar:57 ADMIN_ROLES, /mi-cursada:66 PRACTICA_ROLES. Del lado de acciones: practica-actions.ts:277 PRACTICA_ROLES, practica-postop-actions.ts:34 PRACTICA_ROLES, cirugia-confirm-actions.ts:70 CLIENT_ROLES, cirugia-retire-actions.ts:80 RETIRE_ROLES_SQL. LO QUE ESTO LE HACE AL COMENTARIO DE route-access.ts:62-66. Ese comentario afirma que la lista de CATALOG_ROLES ES la unica decision abierta de la catedra sobre quien ve el catalogo. Con diez combinaciones de gate leyendo los mismos datos, esa frase no puede ser cierta: CATALOG_ROLES gobierna UNA de diez puertas, la de /cirugias. Cambiarla no cambia quien ve el catalogo por las otras nueve. LA CAPA DE LECTORES NO TIENE GATE PROPIO, y esto es hallazgo, no defecto - pero hay que escribirlo porque es lo que hace posible el error. lookups.ts:170-605 entero, practica-detail.ts:98, informe-query.ts:204 y vocabulary-drift.ts:40 no llaman a ningun requireAppUser*: dependen enteramente de quien los llame. coder-terra-ca busco un sitio de llamada externo sin gate aguas arriba y NO ENCONTRO NINGUNO, o sea que hoy el patron se sostiene. Pero significa que la autorizacion de estos datos NO VIVE EN UN LUGAR: vive repartida en diez sitios de llamada, y agregar una pagina nueva que llame a getCirugias sin gate no rompe nada visible. POR QUE ME EQUIVOQUE Y QUE APRENDO. Yo verifique que las dos citas de coder-terra-ca fueran TEXTUALES - y lo eran - y de ahi conclui que el row era correcto. Nunca grepee si CATALOG_ROLES era el unico camino a los datos. Verificar la cita no es verificar el alcance: una cita puede ser exacta y la afirmacion que sostiene puede ser falsa igual, porque el error no esta en lo que dice la linea citada sino en lo que NO se cito. QUEDA PENDIENTE Y ES DECISION MIA, no de la catedra: si se centraliza la autorizacion del catalogo o se acepta explicitamente que sean diez puertas con gates deliberadamente distintos (que es defendible - leer para cargar una practica no es lo mismo que administrar el catalogo). Lo que NO puede quedar es el comentario de route-access.ts:62-66 diciendo que hay una sola decision abierta. Ese comentario se borra en el commit que resuelva esto, no antes y no por separado.
  • wi-cli-venus decision · 6w ago
    Mandada a eq 75, topico terra-quien-ve-el-catalogo. El fallo sobre quien LEE el catalogo es de la catedra y no mio, y lo escribi haciendo explicita la consecuencia que la fila ya identificaba: una lista mas angosta que deje afuera a client no le saca una pantalla, le saca la unica que tiene, o sea que responder eso es decidir si el rol client sigue existiendo. Preferi que esa consecuencia estuviera en la pregunta y no en la implementacion posterior. En paralelo le pedi a coder-terra-ca el estado de hecho que hoy no esta escrito: la matriz de /cirugias por rol y por capacidad, con cita en cada celda, separando lo que decide la constante de ruta de lo que decide un chequeo adentro de la pagina o de la accion, porque son dos limites distintos que se leen como uno. Dos cosas de ese pedido no son matriz sino condiciones: si alguna capacidad esta gateada SOLO en la interfaz sin equivalente del lado del servidor, eso es un hallazgo y quiero saberlo antes que la matriz; y si resulta que client ve menos de lo que el comentario de route-access.ts sugiere, cambia el argumento entero de la eq y hay que saberlo ANTES de que llegue la respuesta, no despues. Le dije explicitamente que no proponga la lista nueva: eso es lo que esta preguntado afuera, y una lane que sugiere la respuesta contamina el fallo que despues vamos a contrastar contra ella.
  • wi-cli-venus blocked · 6w ago
    Esperando eq 75: el fallo de la catedra sobre quien lee el catalogo de cirugias. La matriz de estado de hecho la esta armando coder-terra-ca en paralelo y no depende de la respuesta.
  • wi-cli-venus note · 6w ago
    Matriz de estado de hecho, hecha por coder-terra-ca el 2026-09-01 a pedido mio, con la instruccion explicita de NO proponer la lista nueva - eso es lo que esta preguntado en eq 75, y una lane que sugiere la respuesta contamina el fallo contra el que despues la vamos a contrastar. Evidencia suministrada por esa lane, con lectura de fuente unicamente; los conteos de base los medi yo. QUIEN VE Y QUIEN PUEDE, por rol sembrado. La pagina evalua interseccion de conjuntos de rol, o sea que una cuenta con varios roles recibe la union (route-access.ts:119-131). alumno: no ve la pagina, es el unico de los seis fuera de CATALOG_ROLES. docente y jtp: ven la pagina, el estado de confirmacion de cada fila y las anotaciones de motivo de desconfirmacion. No confirman, no retiran, no ven las filas retiradas. client y bedel: lo mismo, mas confirmar y desconfirmar. No retiran. admin: todo lo anterior, mas retirar y reactivar, y es el unico que recibe la consulta de filas retiradas y ve esa seccion. LO QUE CONTESTA LA PREGUNTA QUE HICE SOBRE client, y sostiene el argumento de la eq en vez de debilitarlo: client no es un espectador. Ve el catalogo activo, el estado de cada fila, y confirma y desconfirma por fila. O sea que el catalogo no es "una pantalla que ademas ve", es su superficie de trabajo. Estrechar la lista de lectura para dejarlo afuera le sacaria lo unico que hace. La eq 75 quedo escrita asi antes de tener esta matriz y la matriz la confirma. DONDE SE DECIDE CADA COSA, que era mi pregunta 1 y es la que evita el error tipico: leer se decide en la constante de ruta y se aplica del lado del servidor en la pagina; confirmar y retirar NO se deciden ahi. Cada uno tiene su propia constante, su propia verificacion en la accion de servidor, y una RE-LECTURA del contrato de rol adentro de la misma sentencia que escribe. Tres capas, no una. Y retirar usa una constante propia en vez de ADMIN_ROLES justamente porque ADMIN_ROLES admitiria a bedel. Son limites distintos que en la pantalla se leen como uno solo. MI PREGUNTA 2, la que pedi ANTES que la matriz: no hay ninguna capacidad gateada solo en la interfaz. Los dos componentes de control declaran por escrito que el render es conveniencia, y las dos acciones tienen la verificacion del lado del servidor mas la re-lectura en SQL. La visibilidad de la ruta tambien es del servidor, no del menu. Y UN HALLAZGO QUE NO ERA LO QUE YO BUSCABA, verificado por mi con grep y contra la base, abierto como TERRA-182: los unicos dos escritores de terraCirugias en produccion son el flip de confirmacion y el flip de retiro. No existe alta. La fuente descarta el rename a proposito y en la misma frase nombra como alternativa "retirar la fila equivocada y crear la correcta" (cirugias/page.tsx:58-61) - o sea que el remedio prescrito se puede empezar y no terminar. Medido: 78 filas, 48 activas, 17 confirmadas, ultima alta 2026-08-22, todas por migracion. ESTO NO CAMBIA LA PREGUNTA DE eq 75 y lo dejo dicho para que nadie las mezcle: 175 es quien LEE el catalogo, 182 es que no hay forma de agregarle una fila. Se tocan en la misma pantalla y son decisiones separadas.
  • wi-cli-venus blocked · 6w ago
    ESCRITO 2026-09-01, ESTABA VACIO. El row llevaba status=blocked con blockedReason EN BLANCO, que es la peor combinacion posible: nadie lo puede desbloquear porque no hay condicion que verificar, y nadie lo revisa porque el estado dice que no hay nada que mirar. Un bloqueo sin condicion declarada no puede expirar. Lo detecto audit-terra-ca en la pasada de tablero de hoy y lo verifique antes de escribir esto. CONDICION VIVA, UNA SOLA, Y ES DE LA CATEDRA, NO DE ARQUITECTURA: quien debe VER la pagina de gestion del catalogo de cirugias. Hoy /cirugias gatea por CATALOG_ROLES, que son cinco roles (src/lib/route-access.ts:62-66, gateado en src/app/cirugias/page.tsx:86), mientras el picker de practicas lee LAS MISMAS cirugias por PRACTICA_ROLES. O sea que hay dos puertas de ancho distinto sobre el mismo catalogo, y cual de las dos es la correcta para la pantalla de GESTION - donde se ve y se cambia el estado de confirmacion del cliente - no lo decidio nadie. Va por eq 75. NO ESTA BLOQUEADO EN CODIGO: el cambio, cuando se decida, es la constante y su re-lectura adentro de la sentencia que escribe, mismo patron de tres capas que ya tienen confirm y retire.
  • wi-cli-venus note · 6w ago
    VIGENTE, releida contra fuente por audit-terra-ca a ciegas el 2026-09-01 08:34, y ADEMAS contesta el predicado que yo habia dejado abierto media hora antes en otras dos filas. LO QUE SIGUE SIENDO CIERTO, con archivo y linea: /cirugias llama requireAppUserPage(CATALOG_ROLES) en src/app/cirugias/page.tsx:89-91, y CATALOG_ROLES es cliente/docente/jtp/bedel/admin (route-access.ts:62-66). /practicas/nueva llama requireAppUserPage(PRACTICA_ROLES) en su page.tsx:27-34, y esos cinco roles son alumno/docente/jtp/bedel/admin (route-access.ts:33-40). O sea que la asimetria que la fila describe esta intacta: ALUMNO entra al picker de practicas y no a la pagina de gestion; CLIENTE al reves. Las dos superficies leen el mismo catalogo de cirugias. LO NUEVO, Y ES LO QUE VALE: el picker no lee la tabla, lee la VISTA. getCirugias va contra vTerraCirugias (src/lib/lookups.ts:313-323) y el predicado de esa vista, documentado en la fuente en 313-317, es deletedAt IS NULL AND isActive. O sea que el picker excluye las borradas Y las retiradas. La pagina de gestion tambien lee por esa vista para su listado principal, y ADEMAS tiene una seccion aparte de filas retiradas que va contra la tabla base con deletedAt IS NULL AND isActive IS FALSE (cirugias/page.tsx:121-188). ESO CIERRA UNA PREGUNTA QUE YO HABIA DEJADO ABIERTA EN TERRA-141 Y TERRA-196 y que me hizo equivocar un numero hoy: cuando esas filas dicen "el campo se pide en las cirugias de Implantologia", el conteo que corresponde es el de ACTIVAS, no el de existentes. Modulo 1 tiene 16 cirugias y 10 activas, ninguna borrada. El usuario que carga una practica ve DIEZ. El 16 no aparece en ninguna superficie de carga; solo lo ve la pagina de gestion, y partido en dos listas. LIMITE QUE audit MARCO SOLA Y QUE RESPETO: leyo el predicado de la vista en la FUENTE, no consulto la base ni midio la poblacion viva. El 16/10 lo medi yo aparte, agrupando por moduloId. Son dos mediciones distintas que coinciden, no una sola. LO QUE LA FILA SIGUE PIDIENDO Y NADIE CONTESTO: si esa asimetria es deliberada. Que un alumno pueda elegir una cirugia del catalogo pero no ver la pagina donde se gestiona puede ser exactamente lo que se quiere, o puede ser que CATALOG_ROLES se haya escrito pensando en otra cosa. Es una decision, no una medicion, y no es mia.
  • wi-cli-venus assigned · 5w ago
    coder02-terra-ca
  • wi-cli-venus assigned · 5w ago
    coder02-terra-cc
  • wi-cli-venus decision · 5w ago
    DECIDED - RATIFIED AS IS, NO CODE CHANGE TO THE GATES. Marker: T175-dec-mtwz03. Decided by the terra PM lane 2026-09-11 under Elazar's 09:27 ART standing delegation. Not Elazar's wording; overrule this row specifically if wrong. MEASURED, not recalled - src/lib/route-access.ts:39 and :66: PRACTICA_ROLES = alumno, docente, jtp, bedel, admin CATALOG_ROLES = client, docente, jtp, bedel, admin They differ by exactly two names: alumno (in the picker, out of /cirugias) and client (in /cirugias, out of the picker). THE ROW CALLED THIS "two doors of different widths over one catalogue". Both widths are correct, and the difference is not an oversight: - alumno IS in the picker because choosing a cirugia while loading your own practica is the primary flow the app exists for. Removing alumno there breaks every student before 1/10. - alumno is NOT in /cirugias because that page is the catalogue ADMINISTRATION view - it is a view of the catalogue as an object to manage, not a value to pick. That is the same exclusion ROSTER_ROLES already makes at :43 for the same stated reason. - client IS in /cirugias because the catedra's own head is the person who owns the catalogue, and is NOT in the picker because a client account does not load practicas. So the sets are not a wide door and a narrow door over one thing. They are two different surfaces that happen to read the same vocabulary, and each is gated on who should be on THAT surface. WHAT ACTUALLY CHANGES: delete the floating comment that says this is undecided, IN THE SAME COMMIT as writing this ruling - the row itself said that is the only way the question stops resurfacing. Nothing else. The row was never blocked in code; it was blocked on nobody being willing to say the current shape was chosen. It was chosen, as of now.
  • wi-cli-venus unblocked · 5w ago
    policy decided T175-dec-mtwz03: both role sets ratified as chosen; only change is deleting the comment that says it is undecided, same commit
  • wi-cli-venus decision · 5w ago
    CORRECTION TO T175-dec-mtwz03, SAME AUTHORITY. Marker: T175-dec-mtwz09. The ruling stands unchanged; the code change I attached to it does not exist. WHAT I GOT WRONG: I wrote "delete the floating comment that says this is undecided, in the same commit". I took that from the eq body, which promised "borro ese comentario en el mismo commit". SEARCHED THE TREE - there is no such comment. The only two src comments calling a policy undecided are src/lib/email/recipients.ts:10 and src/lib/support-queue.ts:14, and both are TERRA-214's coordination-subscription rule, not this row's role sets. WHAT IS ACTUALLY IN THE TREE at src/lib/route-access.ts:62-65 is the CATALOG_ROLES comment, and it is accurate: it explains why `client` comes first and why admin/bedel reach the page. It does not claim the gate is undecided and it does not need editing. SO THIS ROW CLOSES WITH ZERO CODE CHANGE. The gates are ratified as chosen (PRACTICA_ROLES :39, CATALOG_ROLES :66, differing by alumno and client, each correct for its own surface). The row was never blocked in code - it was blocked on nobody being willing to say the current shape was deliberate, and that is now said. THE TWO TERRA-214 COMMENTS WERE STALE FOR A DIFFERENT REASON AND ARE FIXED, since finding them is what proved this row had none: both said the standing subscription RULE was undecided, which stopped being true when TERRA-214's rule was decided today. Updated in place to say the rule is settled and only the membership list is outstanding. That edit belongs to TERRA-214, not here.
  • wi-cli-venus completed · 5w ago
    Ratified as chosen, zero code change (T175-dec-mtwz03 + correction T175-dec-mtwz09). PRACTICA_ROLES and CATALOG_ROLES differ by alumno and client and each set is correct for its own surface: the practica picker is a value-read inside the primary student flow, /cirugias is the catalogue administration view. The comment the eq promised to delete does not exist in the tree.
task
6w ago by wi-cli-venus
5w ago
2026-09-11 12:48