make-app-permission
Use this skill when a request creates, changes, reviews, or debugs Make App single-app permission enforcement. It must be enabled by default for every generated or refactored Make App. Do not omit the IAM proxy, route guards, permission-aware Schema, or permission audits merely because the request focuses on UI, Service, Schema, or runtime work.
This skill owns permission semantics. Use make-app-auth for login/session, make-app-service for Service and Schema transport, makeui for rendering, canvas-table-integration for cell-editor mechanics, and make-app-runtime for packaging/runtime.
Quick start
- Inspect
apps/docs/api.md, Service/UI schema adapters and types, principal-permission code, providers, router, object pages, create/edit forms, submit builders, refresh flow, and tests.
- Read
references/permission-boundaries.md before selecting scope, permissionKey, schema collection, or field access state.
- Read
references/service-principal-permission.md before changing /principal/permission or interpreting IAM fieldAccess.
- Read
references/ui-permission-runtime.md before changing route/action gates, create/read/update field sets, payload filtering, or refresh.
- Read
references/system-field-contract.md before implementing ID/audit create or edit capability.
- Read
references/testing-and-audit.md before implementation and before reporting completion.
- Implement tests first, then the Service/schema boundary, permission pure model, route/action gates, field-set consumers, submit allowlists, and refresh invalidation.
- Run host tests, the behavioral conformance suite, and
node skills/make-app-permission/scripts/audit-make-app-permission.mjs <project-root>. Wire both permission checks into the host's default test, CI, or publish gate; a one-off local run is not a continuous gate.
- When publishing or installing this Skill, run
check-installed-skill-sync.mjs with explicit source and installed directories. When the release changes shared Make response/auth/permission guidance, publish the platform package, run npx skills update qfeius/make-platform-skills, then run the repository-wide check-installed-make-platform-skills-sync.mjs with explicit source and installed Skill roots. Keep these local release checks out of portable host CI.
Required contract
- Expose
/api/make/app/principal/permission; have Service call /api/make/iam/v1/principal/permission with App scope, MakeService.GetResource, and the established login context. This is a direct Make proxy: return every completed IAM response unchanged, including 2xx/4xx/5xx status, Content-Type, and body. Do not request tenant-root scope or upstream platform permission filters. Before strict normalization, classify rows with references/permission-boundaries.md: ignore only clearly unrelated rows, and fail closed for every selected or unclassifiable row.
- Match exact, wildcard, parent, App, entity, IAM namespace-wildcard App resources, and deny correctly. Use the most-specific allow field range; deny wins.
- Keep create, visibility, and editability as separate field-set decisions:
- create form:
createFields ∩ meta.field.read fieldAccess(creatable|readonly|editable|partialMask|fullMask|*);
- list/detail/filter:
fields ∩ meta.field.read fieldAccess(readable states);
- edit/cell edit: visible
fields ∩ meta.field.update fieldAccess(editable|*).
- Keep entity navigation, table headers, and record data independent:
meta.entity.read controls whether a Schema-present entity appears in navigation and can enter its object route; both the navigation and the dynamic route must reject the entity when this permission is absent. meta.field.read controls the authorized columns/table headers; data.record.read controls record/detail requests and rows only. When record read is denied or revoked but entity and fields are authorized, keep the navigation item and table shell with authorized headers, skip every record request, and render an explicit empty row set so cached values cannot remain visible.
- Preserve every access state returned for a field. Current IAM responses may use arrays such as
["creatable", "readonly"] or scalar strings; normalize a supported scalar string to a one-element array and authorize a permission dimension when any state is allowed for that dimension. Never coerce an array with String(value) or template interpolation.
- Treat missing
createFields as empty. Never fall back to fields, and do not consume editableFields for current edit behavior.
- Gate the create entry and submit with
data.record.create only; derive create fields from the matched meta.field.read row and createFields. meta.field.create is not a platform permission point and must not be required, inferred, or emitted. The operation gate never grants field access or bypasses the create-field intersection. Gate update/delete/bulk-update independently with their own operation keys.
- Recompute the latest create/edit allowlist before submit and build payloads from it. Never spread the complete form store into a protected mutation.
- Exclude ID and system audit fields from create capability. Keep existing audit-field edit capability when the field is visible, update-authorized, and supported by the host editor.
- Keep create-only invisible fields available only in create mode. A
creatable access state is not readable or editable.
- Add App/object/fixed-route guards; hiding menus or buttons is not authorization. Recheck handlers before reads and mutations.
- Refresh permission and permission-trimmed Schema in one access generation before data refresh. Invalidate stale permission, Schema, form, and record work; do not close a still-authorized create surface merely because read is revoked.
- Fail closed on permission or Schema failure. Leave row-level
dataCondition enforcement to backend APIs.
- Add Service/schema, permission-model, route/page, payload, special-field, refresh, and negative audit tests.
Reference map
| Task |
Read |
| Platform vs App scope, create/read/update field surfaces, Schema collections, matching |
references/permission-boundaries.md |
Service endpoint, IAM request/response, meta.field.read.fieldAccess |
references/service-principal-permission.md |
| Providers, helpers, routes, create/edit flow, payload, refresh, Lookup |
references/ui-permission-runtime.md |
| Exact ID/audit create exclusions and edit compatibility |
references/system-field-contract.md |
| Required tests, audit signals, completion blockers |
references/testing-and-audit.md |
| Auth/session |
Use make-app-auth |
| Schema/API transport and cache |
Use make-app-service |
| Form/empty-state presentation |
Use makeui |
| Table/cell-editor mechanics |
Use canvas-table-integration |
| Selection, row precheck, batch actions |
Use make-app-actions |
| Runtime gateway and packaging |
Use make-app-runtime |
Audit
node skills/make-app-permission/scripts/audit-make-app-permission.mjs <project-root>
Treat failures as blockers and warnings as review items. The audit is heuristic and never replaces runtime tests.
It rejects obvious fieldAccess state-array coercion through String(...), text helpers, template interpolation, .toString(), or .join() when the coerced value affects normalization output or permission evaluation, including direct control-flow conditions. Diagnostic-only logging, comments, and string literals inside a named normalization helper must not fail the audit, regardless of whether the parameter uses a generic or fieldAccess-specific name. The executable behavior contract remains authoritative.
Also expose a thin host adapter and run the executable behavior contract:
node skills/make-app-permission/scripts/permission-conformance-suite.mjs <host-adapter-module>
If the adapter is TypeScript, run the same command through the host's existing TypeScript runner. Do not add a runtime dependency only for this check. The adapter must delegate to the production permission helpers and create-capability guard; it must not reimplement them in the test.
Keep the audit and conformance runner project-local or install them through a versioned dependency before making them a host gate. Do not hardcode another workspace checkout or a developer home-directory Skill path into portable CI.
For local Skill install/release verification, compare the complete source and installed directories:
node skills/make-app-permission/scripts/check-installed-skill-sync.mjs \
skills/make-app-permission <installed-skill-dir>
The checker reports source-only, installed-only, and content-mismatch files. Pass an explicit install directory; do not embed a developer home path in the Skill or in host CI.
For a release that changes the shared Service/auth/permission contract, update the
installed platform package first, then verify all affected Make App Skills:
npx skills update qfeius/make-platform-skills
node scripts/check-installed-make-platform-skills-sync.mjs \
skills <installed-skills-dir>
Run this only after the source revision has been published through the platform
Skill release flow. It is a local release verification, not portable host CI.
1---2name: make-app-permission3description: Use when generating, refactoring, reviewing, or debugging Make App single-app permission enforcement: /principal/permission, App-scoped IAM matching, permission-aware Schema, entity/field/operation guards, or permission refresh. Triggered by 单应用权限, 权限范围, 字段可新建、可见、可编辑, creatable, createFields, data.record.*, meta.entity.*, meta.field.*, route guards, or URL bypass. Use make-app-actions for selection and batch actions. Does not own platform-admin permissions, auth, generic Service APIs, UI layout, CanvasTable internals, DSL, deployment, or runtime packaging.4---56# make-app-permission78Use this skill when a request creates, changes, reviews, or debugs Make App single-app permission enforcement. It must be enabled by default for every generated or refactored Make App. Do not omit the IAM proxy, route guards, permission-aware Schema, or permission audits merely because the request focuses on UI, Service, Schema, or runtime work.910This skill owns permission semantics. Use `make-app-auth` for login/session, `make-app-service` for Service and Schema transport, `makeui` for rendering, `canvas-table-integration` for cell-editor mechanics, and `make-app-runtime` for packaging/runtime.1112## Quick start13141. Inspect `apps/docs/api.md`, Service/UI schema adapters and types, principal-permission code, providers, router, object pages, create/edit forms, submit builders, refresh flow, and tests.152. Read `references/permission-boundaries.md` before selecting scope, permissionKey, schema collection, or field access state.163. Read `references/service-principal-permission.md` before changing `/principal/permission` or interpreting IAM `fieldAccess`.174. Read `references/ui-permission-runtime.md` before changing route/action gates, create/read/update field sets, payload filtering, or refresh.185. Read `references/system-field-contract.md` before implementing ID/audit create or edit capability.196. Read `references/testing-and-audit.md` before implementation and before reporting completion.207. Implement tests first, then the Service/schema boundary, permission pure model, route/action gates, field-set consumers, submit allowlists, and refresh invalidation.218. Run host tests, the behavioral conformance suite, and `node skills/make-app-permission/scripts/audit-make-app-permission.mjs <project-root>`. Wire both permission checks into the host's default test, CI, or publish gate; a one-off local run is not a continuous gate.229. When publishing or installing this Skill, run `check-installed-skill-sync.mjs` with explicit source and installed directories. When the release changes shared Make response/auth/permission guidance, publish the platform package, run `npx skills update qfeius/make-platform-skills`, then run the repository-wide `check-installed-make-platform-skills-sync.mjs` with explicit source and installed Skill roots. Keep these local release checks out of portable host CI.2324## Required contract2526- Expose `/api/make/app/principal/permission`; have Service call `/api/make/iam/v1/principal/permission` with App scope, `MakeService.GetResource`, and the established login context. This is a direct Make proxy: return every completed IAM response unchanged, including 2xx/4xx/5xx status, Content-Type, and body. Do not request tenant-root scope or upstream platform permission filters. Before strict normalization, classify rows with `references/permission-boundaries.md`: ignore only clearly unrelated rows, and fail closed for every selected or unclassifiable row.27- Match exact, wildcard, parent, App, entity, IAM namespace-wildcard App resources, and deny correctly. Use the most-specific allow field range; deny wins.28- Keep create, visibility, and editability as separate field-set decisions:29 - create form: `createFields ∩ meta.field.read fieldAccess(creatable|readonly|editable|partialMask|fullMask|*)`;30 - list/detail/filter: `fields ∩ meta.field.read fieldAccess(readable states)`;31 - edit/cell edit: visible `fields ∩ meta.field.update fieldAccess(editable|*)`.32- Keep entity navigation, table headers, and record data independent: `meta.entity.read` controls whether a Schema-present entity appears in navigation and can enter its object route; both the navigation and the dynamic route must reject the entity when this permission is absent. `meta.field.read` controls the authorized columns/table headers; `data.record.read` controls record/detail requests and rows only. When record read is denied or revoked but entity and fields are authorized, keep the navigation item and table shell with authorized headers, skip every record request, and render an explicit empty row set so cached values cannot remain visible.33- Preserve every access state returned for a field. Current IAM responses may use arrays such as `["creatable", "readonly"]` or scalar strings; normalize a supported scalar string to a one-element array and authorize a permission dimension when any state is allowed for that dimension. Never coerce an array with `String(value)` or template interpolation.34- Treat missing `createFields` as empty. Never fall back to `fields`, and do not consume `editableFields` for current edit behavior.35- Gate the create entry and submit with `data.record.create` only; derive create fields from the matched `meta.field.read` row and `createFields`. `meta.field.create` is not a platform permission point and must not be required, inferred, or emitted. The operation gate never grants field access or bypasses the create-field intersection. Gate update/delete/bulk-update independently with their own operation keys.36- Recompute the latest create/edit allowlist before submit and build payloads from it. Never spread the complete form store into a protected mutation.37- Exclude ID and system audit fields from create capability. Keep existing audit-field edit capability when the field is visible, update-authorized, and supported by the host editor.38- Keep create-only invisible fields available only in create mode. A `creatable` access state is not readable or editable.39- Add App/object/fixed-route guards; hiding menus or buttons is not authorization. Recheck handlers before reads and mutations.40- Refresh permission and permission-trimmed Schema in one access generation before data refresh. Invalidate stale permission, Schema, form, and record work; do not close a still-authorized create surface merely because read is revoked.41- Fail closed on permission or Schema failure. Leave row-level `dataCondition` enforcement to backend APIs.42- Add Service/schema, permission-model, route/page, payload, special-field, refresh, and negative audit tests.4344## Reference map4546| Task | Read |47| --- | --- |48| Platform vs App scope, create/read/update field surfaces, Schema collections, matching | `references/permission-boundaries.md` |49| Service endpoint, IAM request/response, `meta.field.read.fieldAccess` | `references/service-principal-permission.md` |50| Providers, helpers, routes, create/edit flow, payload, refresh, Lookup | `references/ui-permission-runtime.md` |51| Exact ID/audit create exclusions and edit compatibility | `references/system-field-contract.md` |52| Required tests, audit signals, completion blockers | `references/testing-and-audit.md` |53| Auth/session | Use `make-app-auth` |54| Schema/API transport and cache | Use `make-app-service` |55| Form/empty-state presentation | Use `makeui` |56| Table/cell-editor mechanics | Use `canvas-table-integration` |57| Selection, row precheck, batch actions | Use `make-app-actions` |58| Runtime gateway and packaging | Use `make-app-runtime` |5960## Audit6162```bash63node skills/make-app-permission/scripts/audit-make-app-permission.mjs <project-root>64```6566Treat failures as blockers and warnings as review items. The audit is heuristic and never replaces runtime tests.67It rejects obvious `fieldAccess` state-array coercion through `String(...)`, text helpers, template interpolation, `.toString()`, or `.join()` when the coerced value affects normalization output or permission evaluation, including direct control-flow conditions. Diagnostic-only logging, comments, and string literals inside a named normalization helper must not fail the audit, regardless of whether the parameter uses a generic or `fieldAccess`-specific name. The executable behavior contract remains authoritative.6869Also expose a thin host adapter and run the executable behavior contract:7071```bash72node skills/make-app-permission/scripts/permission-conformance-suite.mjs <host-adapter-module>73```7475If the adapter is TypeScript, run the same command through the host's existing TypeScript runner. Do not add a runtime dependency only for this check. The adapter must delegate to the production permission helpers and create-capability guard; it must not reimplement them in the test.76Keep the audit and conformance runner project-local or install them through a versioned dependency before making them a host gate. Do not hardcode another workspace checkout or a developer home-directory Skill path into portable CI.7778For local Skill install/release verification, compare the complete source and installed directories:7980```bash81node skills/make-app-permission/scripts/check-installed-skill-sync.mjs \82 skills/make-app-permission <installed-skill-dir>83```8485The checker reports source-only, installed-only, and content-mismatch files. Pass an explicit install directory; do not embed a developer home path in the Skill or in host CI.8687For a release that changes the shared Service/auth/permission contract, update the88installed platform package first, then verify all affected Make App Skills:8990```bash91npx skills update qfeius/make-platform-skills92node scripts/check-installed-make-platform-skills-sync.mjs \93 skills <installed-skills-dir>94```9596Run this only after the source revision has been published through the platform97Skill release flow. It is a local release verification, not portable host CI.