Skip to content

docs: lock down permission string format (<id>:<action>)#19

Merged
klinux merged 1 commit into
mainfrom
docs/perm-format-guardrails
May 28, 2026
Merged

docs: lock down permission string format (<id>:<action>)#19
klinux merged 1 commit into
mainfrom
docs/perm-format-guardrails

Conversation

@klinux

@klinux klinux commented May 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • New CLAUDE.md section "Permission strings — exactly two segments" declaring the format explicitly with worked correct/wrong examples (including the literal my-module:conta:read trap).
  • New /check-module validation 2.6 — Formato das permissoes that catches malformed strings in permissions[] and requiredPermission (extra colons, resource ≠ module id, empty segments, non-kebab actions). Subsequent sections renumbered.

Why

A developer wrote my-module:conta:read in permissions[] and Claude Code didn't push back. Investigating, the project never documents the format explicitly — only shows 2-segment examples — and the $schema URL referenced in module.json doesn't actually exist in corabank/platform-backoffice-shell, so editors and LLMs get no formal hint. The shell parses with indexOf(":") (split on the first colon), so my-module:conta:read silently parses to action="conta:read" — a dead permission no RBAC role can ever grant. The module registers fine, the sidebar renders, and users get permanent permission-denied with nothing in logs.

This PR closes two gaps:

  1. Prevention — CLAUDE.md now states the rule on the first read, so Claude Code stops extrapolating from IAM/Casbin priors.
  2. Detection/check-module flags violations locally before they ship.

A follow-up worth doing in another repo: publish module.schema.json in @platform/shell-contract with pattern: ^[a-z][a-z0-9-]*:[a-z][a-z0-9_-]*$ so editors enforce the format at edit time too.

Test plan

  • Run /check-module on a module with "permissions": ["my-module:conta:read"] and confirm it reports a format error.
  • Verify the same check fires on requiredPermission inside navigation[]/perspectives[].
  • Spot-check section numbering in .claude/skills/check-module/SKILL.md (2.6 → 2.12) renders cleanly.

🤖 Generated with Claude Code

CLAUDE.md never declared the permission string format explicitly — only
examples — and the `$schema` referenced in module.json is not published,
so editors and LLMs get no formal hint. The shell parses with
`indexOf(":")`, which silently accepts malformed inputs like
`my-module:conta:read` (action becomes "conta:read") and yields a dead
permission no RBAC role can ever grant.

- CLAUDE.md: new "Permission strings — exactly two segments" section
  near the nav docs, with the rule, the why (silent failure), and four
  worked examples (correct + three wrong patterns).
- check-module skill: new check 2.6 "Formato das permissoes" validates
  declared `permissions[]` and `requiredPermission` in nav/perspectives
  against `<id>:<action>`. Subsequent sections renumbered.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@klinux

klinux commented May 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot review

Copilot AI commented May 28, 2026

Copy link
Copy Markdown

@copilot review

Revisão das mudanças

As alterações são exclusivamente em arquivos Markdown (documentação e skill) e estão bem estruturadas. Seguem os pontos relevantes:

CLAUDE.md — Seção "Permission strings — exactly two segments"

Positivos:

  • Explica o mecanismo de falha silenciosa com precisão (indexOf(":")action="conta:read")
  • Exemplos concretos cobrindo os casos mais comuns de erro
  • Orienta a codificação de sub-recurso via -/_ em vez de :

⚠️ Observação menor: O título diz "two segments" mas o module.json usa inglês misto enquanto o restante do guia está em PT-BR. Não é bloqueante, mas poderia ser padronizado.


SKILL.md — Check 2.6 "Formato das permissoes"

Positivos:

  • validate_perm_format() trata corretamente todos os casos: sem colon, múltiplos colons, segmento vazio, resource ≠ module id, e action fora do kebab-case
  • Uso de awk -F: '{print NF-1}' é robusto para contar colons
  • O posicionamento antes do check 2.7 (orphan check) é correto para evitar ruído em strings já quebradas
  • A justificativa de error vs warn está bem documentada inline
  • Renumeração de 2.7→2.12 está consistente

⚠️ Ponto de atenção: O while IFS= read -r p vai iterar com p="" quando o jq retornar string vazia (ex.: permissions: []). Isso está tratado pela guarda [ -z "$perm" ] && return no início da função — correto.

⚠️ Ponto de atenção: A regex de action ^[a-z][a-z0-9_-]*$ permite _ (ex.: invoice_approve), consistente com o exemplo no CLAUDE.md. OK.


Conclusão

As mudanças são precisas, coerentes com o problema relatado e não introduzem riscos. O PR está pronto para merge do ponto de vista de qualidade de código.

Copilot finished work on behalf of klinux May 28, 2026 15:15
@klinux klinux merged commit 5cdc4e1 into main May 28, 2026
3 checks passed
@klinux klinux deleted the docs/perm-format-guardrails branch May 28, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants