@mybuildex/pkg 0.6.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -51,6 +51,41 @@ createAuthMiddleware({
51
51
  createTenantMiddleware({getTenantClient, defaultClient, strictTenant: true});
52
52
  ```
53
53
 
54
+ ## 0.8.0 — API single-tenant só aceita token do tenant default
55
+
56
+ **Muda comportamento por padrão** (⚠️) em quem usa `tenantAware: false` — hoje só o `v1_core`.
57
+
58
+ - ⚠️ `createAuthMiddleware({tenantAware: false})` recusa com **403** (`Token de escola não é aceito nesta API`) todo token que carrega o claim `firebase.tenant`, antes de chamar o `verifyIdToken`; a regra é reconferida no token verificado e no cache. O Auth default do firebase-admin valida a assinatura de token de qualquer tenant do projeto (só o `TenantAwareAuth` confere o claim) — o que barrava o usuário de escola era, por acaso, a busca do usuário na checagem de revogação (401). Rotas públicas e `internalAuth` não mudam.
59
+ - Efeito no core: toda chamada com token de escola responde 403, inclusive o `GET /v1/convert` que o front da plataforma faz com o token do usuário da escola.
60
+ - `aclAllows(request, "recurso.acao" | lista | {anyOf, allOf})` — a regra da ACL dentro do service, para decidir o **escopo**: quem tem a permissão de gestão do recurso vê tudo (mesmo sem `full`); quem entrou por uma entrada de papel (professor, aluno, responsável, membro) vê só o que é seu. Serviço interno passa; sem usuário ou com `permissions_error` nega; entrada inexistente no mapa lança `AclConfigError`. Substitui o uso de `is_full` como "é gestão".
61
+ - `ACL_MAP` regerado do `src/utils/permissions.js` do front, agora com `onboarding_queue` (fila da matrícula online) e as entradas de papel novas.
62
+
63
+ ## 0.7.0 — ACL por endpoint, auditoria de escrita e permissões
64
+
65
+ Módulos novos, todos opt-in (API que não os registra não muda nada). Nova dependência: `redis`.
66
+
67
+ - **Auditoria** — `createMultitenantPrisma({..., audit: {api, tables: "*"}})` aplica uma extensão Prisma que registra toda escrita (create/update/upsert/delete e `*Many`) em `audit_logs` da escola: quem (uid, e-mail, `users.id`, `users.id_people`, `peoples.name`), rota, ação de ACL, antes/depois (no update, só o diff) e status. `createAuditPlugin({api, getTenantClient})` abre o contexto por request e grava num único INSERT por schema no `onSend`, **antes** da resposta (no Cloud Run a CPU é cortada depois). Todo 403 vira linha `acl_denied`/`forbidden` (limite de 30 por usuário+rota por minuto) e cada request gera um log `http_access`. Falha na gravação nunca derruba a escrita (log `audit_write_failed`). Exige a tabela `audit_logs` (migrations `2026_09_29_000173`–`000175` do mybuilder-mysql). SQL cru: `auditRaw()`.
68
+ - **ACL por endpoint** — `createAclPlugin({api, mode})` uma vez no `loadPlugins` + `useModuleAcl(fastify, router, overrides?, {resource?})` no início de cada controller. A regra vem do mapa do front (`ACL_MAP`, gerado de `mybuilder-plataforma-front/src/utils/permissions.js` — o mesmo agregador que o front usa, com a ordem dos spreads — por `npm run acl:generate`; o teste `acl-map.spec.ts` acusa divergência). Ações padrão do CRUD gerado: `ALL→list`, `FIND→find`, `PAGINATE→paginate`, `TRASH→trash` (recurso sem a ação própria cai em `list`), `CREATE/CLONE→add`, `UPDATE→edit`, `REMOVE→remover`, `RESTORE→restore`, `DELETE→delete`. Overrides: `"recurso.acao"`, lista (qualquer uma libera), `{anyOf, allOf}`, `"@authenticated"`, `"@public"`. Modos: `off`, `report` (só loga `acl_would_deny`) e `enforce` (403). `getAclRouteReport(fastify)` lista rotas sem ACL ou com configuração inválida (para teste de cobertura).
69
+ - **Permissões** — `createPermissionsResolver({redis})` como `onTenantResolved` do tenant middleware: preenche `request.permissions`, `is_full`/`is_teacher`/`is_student`/`is_responsible` pela cadeia users → users_profiles → profiles_policies → policies_rules → rules_permissions → permissions. Fail-closed (erro = tudo false + `permissions_error`). Cache Redis versionado por escola; `invalidatePermissionsCache(redis, idSchool)` (INCR, O(1)) depois de escrever em perfis/políticas/regras/permissões.
70
+ - **Redis** — `createRedisClient()` lê o JSON da env `REDIS`; best-effort (sem env, JSON inválido ou falha → `undefined`), timeout de conexão de 3 s.
71
+ - **Serviço interno** — request autenticado pelo `internalAuth` do auth (`request.internal === true`) não passa pela ACL, não consulta permissões e entra na auditoria com `origin = SERVICE`.
72
+
73
+ ```ts
74
+ const mt = createMultitenantPrismaMariaDb<PrismaClient>({..., audit: {api: settings.PREFIX, tables: "*"}});
75
+
76
+ // loadPlugins — depois do request-scope, antes do autoload dos módulos
77
+ const redis = await createRedisClient();
78
+ await createAuditPlugin({api: settings.PREFIX, getTenantClient})(fastify);
79
+ await createAclPlugin({api: settings.PREFIX, mode: aclMode()})(fastify); // off | report | enforce
80
+
81
+ createTenantMiddleware({getTenantClient, defaultClient, strictTenant: true,
82
+ onTenantResolved: createPermissionsResolver({redis})});
83
+
84
+ // cada controller
85
+ useModuleAcl(fastify, citiesRouter);
86
+ useModuleAcl(fastify, payRouter, {PUBLIC_HASH: "@public", SETTLE: "pay.settle"});
87
+ ```
88
+
54
89
  ## 0.6.0 — segurança e confiabilidade
55
90
 
56
91
  Correções em módulos existentes. **Três mudam comportamento por padrão** (marcadas com ⚠️) — conferir antes de atualizar uma API.
@@ -0,0 +1,3 @@
1
+ import { AclMap, AclRule } from "./check";
2
+ /** O usuário do request passa na regra (`recurso.acao`, lista, {anyOf, allOf})? */
3
+ export declare function aclAllows(request: any, rule: AclRule, map?: AclMap): boolean;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.aclAllows = aclAllows;
4
+ // Checagem de ACL DENTRO do service, com a mesma regra do guard da rota.
5
+ //
6
+ // A ACL da rota decide quem entra no endpoint. Dentro dele, o service ainda
7
+ // precisa decidir o ESCOPO: quem tem a permissão de gestão do recurso
8
+ // (ex.: `classes.list`) vê tudo; quem entrou por uma entrada de papel
9
+ // (professor, aluno, responsável, membro) vê só o que é seu. Antes os
10
+ // services usavam `is_full` para isso — o que deixava a equipe da escola sem
11
+ // `full` presa no recorte de professor. `aclAllows` responde com o mapa do
12
+ // front e as permissões do request, igual ao guard:
13
+ //
14
+ // if (!aclAllows(request, "pay_checkouts.list")) where.id_people = minhaPessoa;
15
+ //
16
+ // Regras: serviço interno (auth internalAuth) passa; sem usuário ou com
17
+ // permissions_error nega; `full` libera tudo; entrada inexistente no mapa
18
+ // lança AclConfigError (erro de programação, não de permissão).
19
+ const map_generated_1 = require("./map.generated");
20
+ const check_1 = require("./check");
21
+ const cache = new WeakMap();
22
+ function resolved(rule, map) {
23
+ let byMap = cache.get(map);
24
+ if (!byMap) {
25
+ byMap = new Map();
26
+ cache.set(map, byMap);
27
+ }
28
+ const key = JSON.stringify(rule);
29
+ let r = byMap.get(key);
30
+ if (!r) {
31
+ r = (0, check_1.resolveAclRule)(rule, map);
32
+ byMap.set(key, r);
33
+ }
34
+ return r;
35
+ }
36
+ /** O usuário do request passa na regra (`recurso.acao`, lista, {anyOf, allOf})? */
37
+ function aclAllows(request, rule, map = map_generated_1.ACL_MAP) {
38
+ const r = resolved(rule, map);
39
+ if (request?.internal === true)
40
+ return true;
41
+ if (r.kind === "public")
42
+ return true;
43
+ const uid = request?.user_id ?? request?.user?.uid;
44
+ if (!uid)
45
+ return false;
46
+ if (r.kind === "authenticated")
47
+ return true;
48
+ if (request.permissions_error)
49
+ return false;
50
+ const permissions = Array.isArray(request.permissions) ? request.permissions : [];
51
+ return (0, check_1.evaluateAclRule)(permissions, r);
52
+ }
53
+ //# sourceMappingURL=allows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allows.js","sourceRoot":"","sources":["../../src/acl/allows.ts"],"names":[],"mappings":";;AAoCA,8BAUC;AA9CD,yEAAyE;AACzE,EAAE;AACF,4EAA4E;AAC5E,sEAAsE;AACtE,sEAAsE;AACtE,sEAAsE;AACtE,6EAA6E;AAC7E,2EAA2E;AAC3E,oDAAoD;AACpD,EAAE;AACF,kFAAkF;AAClF,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,gEAAgE;AAChE,mDAAwC;AACxC,mCAA0F;AAE1F,MAAM,KAAK,GAAG,IAAI,OAAO,EAAwC,CAAC;AAElE,SAAS,QAAQ,CAAC,IAAa,EAAE,GAAW;IACxC,IAAI,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QAClB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,CAAC,CAAC,EAAE,CAAC;QACL,CAAC,GAAG,IAAA,sBAAc,EAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9B,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,CAAC,CAAC;AACb,CAAC;AAED,mFAAmF;AACnF,SAAgB,SAAS,CAAC,OAAY,EAAE,IAAa,EAAE,MAAc,uBAAO;IACxE,MAAM,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC9B,IAAI,OAAO,EAAE,QAAQ,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC;IACnD,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACvB,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,OAAO,CAAC,iBAAiB;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,WAAW,GAAa,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5F,OAAO,IAAA,uBAAe,EAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,32 @@
1
+ export type AclMap = Readonly<Record<string, Readonly<Record<string, readonly string[]>>>>;
2
+ /** Regra de ACL de uma rota. Entradas no formato `recurso.acao` do mapa do front. */
3
+ export type AclRule = string | string[] | {
4
+ anyOf?: string[];
5
+ allOf?: string[];
6
+ }
7
+ /** Qualquer usuário autenticado (a auth já barrou quem não tem token). */
8
+ | "@authenticated"
9
+ /** Rota pública: a ACL não se aplica. */
10
+ | "@public";
11
+ export interface ResolvedAclRule {
12
+ kind: "entries" | "authenticated" | "public";
13
+ /** Entradas `recurso.acao` que liberam (qualquer uma). */
14
+ anyOf: string[];
15
+ /** Entradas `recurso.acao` que precisam liberar TODAS. */
16
+ allOf: string[];
17
+ /** União dos identificadores do anyOf (o que o isAclArray recebe). */
18
+ anyOfIds: string[];
19
+ /** Identificadores de cada entrada do allOf. */
20
+ allOfIds: string[][];
21
+ }
22
+ export declare class AclConfigError extends Error {
23
+ constructor(message: string);
24
+ }
25
+ /** Espelho do isAclArray do front: `required` é a lista `acl` de uma entrada. */
26
+ export declare function checkAcl(userPermissions: readonly string[] | null | undefined, required: readonly string[]): boolean;
27
+ /** Identificadores de uma entrada `recurso.acao` (lança se não existir no mapa). */
28
+ export declare function aclEntryIds(entry: string, map?: AclMap): readonly string[];
29
+ /** Valida a regra contra o mapa e pré-calcula os identificadores. */
30
+ export declare function resolveAclRule(rule: AclRule, map?: AclMap): ResolvedAclRule;
31
+ /** Avalia a regra já resolvida contra as permissões do usuário. */
32
+ export declare function evaluateAclRule(userPermissions: readonly string[] | null | undefined, rule: ResolvedAclRule): boolean;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ // Checagem de ACL — espelho EXATO do `isAclArray` do front
3
+ // (src/utils/validations.js + utils/roles.js do front da plataforma):
4
+ //
5
+ // - libera se o usuário tem QUALQUER identificador da lista (OR);
6
+ // - papéis aceitam o nome em en ou pt-BR (teacher/professor, student/aluno):
7
+ // 'teacher' na lista libera quem tem 'professor' e vice-versa;
8
+ // - `full` libera tudo;
9
+ // - lista só com nomes de UM papel (['teacher'], ['teacher','professor'],
10
+ // ['aluno']...) nega sempre (regra do front: papel sozinho não libera ação).
11
+ //
12
+ // Como o front aplica a mesma lista para mostrar/esconder botão e rota, a
13
+ // API não pode ser nem mais nem menos permissiva que isso.
14
+ //
15
+ // Uma rota da API pode aceitar MAIS DE UMA entrada do mapa (`recurso.acao`):
16
+ // a mesma chamada é feita por telas diferentes (ex.: o diário do professor
17
+ // grava em classes_dailys pela tela de turmas, liberada por classes.daily).
18
+ // - lista/`anyOf`: a união dos identificadores das entradas, avaliada de
19
+ // uma vez (qualquer um libera);
20
+ // - `allOf`: cada entrada avaliada à parte — todas precisam liberar.
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ exports.AclConfigError = void 0;
23
+ exports.checkAcl = checkAcl;
24
+ exports.aclEntryIds = aclEntryIds;
25
+ exports.resolveAclRule = resolveAclRule;
26
+ exports.evaluateAclRule = evaluateAclRule;
27
+ const map_generated_1 = require("./map.generated");
28
+ const roles_1 = require("./roles");
29
+ class AclConfigError extends Error {
30
+ constructor(message) {
31
+ super(message);
32
+ this.name = "AclConfigError";
33
+ }
34
+ }
35
+ exports.AclConfigError = AclConfigError;
36
+ /** Espelho do isAclArray do front: `required` é a lista `acl` de uma entrada. */
37
+ function checkAcl(userPermissions, required) {
38
+ const acl = Array.isArray(userPermissions) ? userPermissions.map(String) : [];
39
+ const names = required.map(n => String(n).trim());
40
+ let result = false;
41
+ for (const name of names) {
42
+ if ((0, roles_1.hasAclName)(acl, name))
43
+ result = true;
44
+ }
45
+ if ((0, roles_1.isSingleRoleList)(names))
46
+ return false;
47
+ return result || acl.includes("full");
48
+ }
49
+ /** Identificadores de uma entrada `recurso.acao` (lança se não existir no mapa). */
50
+ function aclEntryIds(entry, map = map_generated_1.ACL_MAP) {
51
+ const dot = entry.lastIndexOf(".");
52
+ if (dot <= 0 || dot === entry.length - 1) {
53
+ throw new AclConfigError(`entrada de ACL inválida: "${entry}" (use recurso.acao, ex.: classes.edit)`);
54
+ }
55
+ const resource = entry.slice(0, dot);
56
+ const action = entry.slice(dot + 1);
57
+ const ids = map[resource]?.[action];
58
+ if (!ids)
59
+ throw new AclConfigError(`entrada de ACL inexistente no mapa do front: "${entry}"`);
60
+ return ids;
61
+ }
62
+ function union(lists) {
63
+ const out = [];
64
+ for (const list of lists)
65
+ for (const id of list)
66
+ if (!out.includes(id))
67
+ out.push(id);
68
+ return out;
69
+ }
70
+ /** Valida a regra contra o mapa e pré-calcula os identificadores. */
71
+ function resolveAclRule(rule, map = map_generated_1.ACL_MAP) {
72
+ if (rule === "@authenticated" || rule === "@public") {
73
+ return { kind: rule === "@public" ? "public" : "authenticated", anyOf: [], allOf: [], anyOfIds: [], allOfIds: [] };
74
+ }
75
+ let anyOf;
76
+ let allOf;
77
+ if (typeof rule === "string") {
78
+ anyOf = [rule];
79
+ allOf = [];
80
+ }
81
+ else if (Array.isArray(rule)) {
82
+ anyOf = [...rule];
83
+ allOf = [];
84
+ }
85
+ else if (rule && typeof rule === "object") {
86
+ anyOf = [...(rule.anyOf ?? [])];
87
+ allOf = [...(rule.allOf ?? [])];
88
+ }
89
+ else {
90
+ throw new AclConfigError(`regra de ACL inválida: ${JSON.stringify(rule)}`);
91
+ }
92
+ if (anyOf.length === 0 && allOf.length === 0) {
93
+ throw new AclConfigError("regra de ACL vazia: informe ao menos uma entrada recurso.acao");
94
+ }
95
+ return {
96
+ kind: "entries",
97
+ anyOf,
98
+ allOf,
99
+ anyOfIds: union(anyOf.map(e => aclEntryIds(e, map))),
100
+ allOfIds: allOf.map(e => [...aclEntryIds(e, map)]),
101
+ };
102
+ }
103
+ /** Avalia a regra já resolvida contra as permissões do usuário. */
104
+ function evaluateAclRule(userPermissions, rule) {
105
+ if (rule.kind !== "entries")
106
+ return true;
107
+ if (rule.anyOf.length > 0 && !checkAcl(userPermissions, rule.anyOfIds))
108
+ return false;
109
+ for (const ids of rule.allOfIds)
110
+ if (!checkAcl(userPermissions, ids))
111
+ return false;
112
+ return true;
113
+ }
114
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/acl/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare const ACL_MAP: Readonly<Record<string, Readonly<Record<string, readonly string[]>>>>;