Skip to content

Enforce every grammar key in every consumer - #129

Merged
sebastiaoteixeira merged 101 commits into
mainfrom
fix/grammar-enforcement
Nov 1, 2026
Merged

sebastiaoteixeira merged 101 commits into
mainfrom
fix/grammar-enforcement

Conversation

@sebastiaoteixeira

Copy link
Copy Markdown
Collaborator

Every grammar key is either enforced in every consumer (dev server, generated FastAPI, DRF and raw ASGI backends, UI generator) or rejected by schema validation.

All versions

  • Every spec schema object is closed: unknown or misplaced keys fail validation.
  • filter and writeFields no longer exist; role: inside a long-form given: rule is rejected. Per-role writable fields are expressed as separate operations with their own service input:.
  • Soft deletion hides removed rows from every generated query in the dev server and every backend.
  • Readonly fields are rejected in request bodies and filled by the server; DTOs share one field base, with a partial payload for updates.
  • Datetimes are stored as canonical UTC strings; field defaults are stored in the canonical form of their field.
  • Nested properties/additionalProperties are validated as nested models with extra keys forbidden.
  • Role grants are limited to the caller's held roles; anonymous register/create cannot assign roles.
  • Anonymous callers get 401 unless an allow rule can admit them; when over a document acts as a row filter on list routes.
  • <collection> by <param> binds the record the route addresses.
  • Typed request bindings resolve path parameters through every request part.
  • Offset pagination breaks sort ties on the id.
  • DRF views run on adrf with the same routing, statuses and access as the other targets; raw ASGI handlers keep per-controller access.

0.1

  • options.strict, indexes, security.redaction, ref store: embed/expand and OIDC discovery_url/claim_mapping/auto_provision are removed.
  • Collection roles and their hierarchy are kept; a replace without access of its own uses the update access.
  • The mongo block is the default datastore; the dev server runs 0.1 specs.
  • security.headers.enableStandard sends the standard security headers in every backend.

0.2

  • Top-level roles: is removed; role hierarchies live in entities.<e>.roles.hierarchy.
  • Repository softDelete: <timestampField> and per-operation includeDeleted: true on custom repository operations.
  • Repository ttl: { field, seconds } expires rows on every datastore (MongoDB TTL index; SQL row filter and purge).
  • api.operations.defaults accepts only CRUD switches and api.operations.auth only register/login; auth.login: false generates no login route.
  • Standard security headers are sent by default; api.securityHeaders: false turns them off.
  • api.port is honoured by stackform run, deploy, DRF and the UI.
  • deploy.mongo.local is honoured and defaults from datastores.
  • Service abstract/extends generate abstract service base classes; custom operations run through service methods.
  • SAML: provider keys invalid for type: saml are rejected, relations are applied in the callback, SAML login works in the dev server, and replayed or malformed responses are rejected.

0.3

  • Same changes as 0.2, plus: root input: and entities.*.auth.bindings are removed (via: replaces bindings); imports accepts only the object form.

UI

  • Requests go through declared routes, pagination, roles and the access matrix; pages and actions are gated on it.
  • Forms send typed, writable-only bodies and cleared fields as null; the ui block is validated against the pack manifest.

Docs and examples

  • User docs describe the enforced grammar; pages about removed keys are deleted.
  • The access-control example binds owners to the caller, restricts user deletion to admins and filters sensitive rows by owner.

… validation

Validate the raw spec, including the ui block, before any transform. Drop
filter, writeFields, long-form role, top-level roles, SAML issuer/audience/trust,
0.3 root input and auth.bindings, string imports in 0.3, options, security
redaction, 0.1 OIDC discovery/claim mapping/auto-provision, indexes, store and
expand, together with their key-specific checks and IR fields. Add a guard test
for schema keys without a consumer.
…the dev server and every generated backend

Declared queries resolve bindings and execute in a vendored runtime (Mongo and SQL), handlers
receive a single HandlerRequest, and routes calling an operation no handler or repository
provides, or paginating a non-list operation, are rejected at parse time.
List routes filter rows by the access rules in memory, in Mongo and in SQL;
<collection> by <param> loads the named record; is null over request input
holds only for absent keys; the refusal reason applies in every version.
Nested properties, additionalProperties, format, items, defaults, strict
scalars, readonly fields and DTO-typed bodies are enforced by the dev server
and the generated FastAPI, DRF and raw backends. Each collection gets one
<Collection>Fields payload that create and replace extend and update makes
partial. Field defaults must conform to their own config and ref fields must
name a declared entity. An empty PATCH returns 200.
Security headers on by default with per-version off switches, CORS and
pagination for 0.1, session.ttl as the access-token lifetime, deploy
port and mongo.local defaults, api.port as the run default, 0.1 roles
and shared validators, mongo beside record datastores rejected, refresh
without a MongoDB store rejected, dev API-key lookup on the stored field,
and examples that build on every backend.
…through service methods

Extending services and repositories merge their ancestors' configuration, minified
services share their input and forwarding with every operation, and handlers and
repository operations receive the same HandlerRequest in every backend.
…in every backend

Identity creates keep a client-chosen role only on authenticated routes, managed roles
start at their default, readonly fields are never written, auth.login: false serves no
login route, optional raw fields accept null, and raw handlers and DRF views are named
per path so routes sharing a collection keep their own access rules.
…ested CORS headers and reject inconsistent mongo settings

Order DRF routes so literal segments precede parameters, keep blank query values for limit validation, report schema errorMessage annotations, and add regression tests for each target.
…elds, validate bodies after access checks and give DTOs a partial update payload

SQL datetime columns bind ISO strings; raw payloads use the shared Model helper; raw and DRF responses hide stored credentials.
…p-safe Mongo client, spec-path routing and 200/422 statuses matching the other targets
# Conflicts:
#	src/yaml_api_generator/generators/backend/drf/generator.py
#	src/yaml_api_generator/generators/backend/drf/templates/views.py.jinja
#	src/yaml_api_generator/generators/backend/fastapi/generator.py
#	src/yaml_api_generator/generators/backend/raw/generator.py
#	src/yaml_api_generator/generators/backend/raw/templates/login_routes.py.jinja
#	src/yaml_api_generator/generators/backend/raw/templates/routes.py.jinja
#	src/yaml_api_generator/generators/backend/raw/templates/validation.py.jinja
#	src/yaml_api_generator/generators/backend/utils.py
#	src/yaml_api_generator/server/common/pipeline_builder.py
#	src/yaml_api_generator/server/common/steps/repositories.py
#	src/yaml_api_generator/server/common/steps/validation.py
#	src/yaml_api_generator/server/fastapi/factory.py
…ults and refs in every field map of every version
…eSQL and on v0.1 collections, with DTO datetimes
…DRF by path and normalize the handler request

Raw and DRF render services and repositories from shared layers, run operations through the service, serve one DRF view per path in route precedence, and hand handlers the last value of repeated query keys, an object body and a principal without credentials.
…ter sensitive rows by owner in the access-control example
…route record bindings over HTTP on every backend

Document explicit-controller access defaults, operations overrides and their precedence, and record bindings on custom routes.
…ation routes, make declared soft-delete fields readonly, reject presence keys on array items and check service input refs
…and pagination envelopes across every backend

Abstract repositories accept crud, lifecycle and parameterised operations; queries naming a collection run on its datastore;
raw ASGI answers 405 with Allow; integer numbers stay integers in FastAPI and SQL; service switches must name a provided operation.
…rver and backend, and name the top-level roles fixture after its case
…server and FastAPI target, offered by the UI and rejected by raw and DRF
…n rejects a credential provider without an identifier
…k operations, unique indexes and stored files

includeDeleted widens reads only; declared SQL deletes stamp removal; expired rows are purged with their files.
…he page

The crud view builds a Delete page from its delete slot; detail pages delete through it.
Pack props declare item types and defaults, and the guard test checks each component's
props are read by its template.
@sebastiaoteixeira
sebastiaoteixeira merged commit a62b073 into main Nov 1, 2026
2 checks passed
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.

1 participant