AUSUS v0.2.0-beta.1 — Pagination, filtering, sorting
First beta of the v0.2 line. Ships the three runtime features that were
pinned as beta blockers in the v0.2.0-beta.1 roadmap,
plus the DX and release-engineering hardening that landed in parallel.
ViewSchema wire bumps from 1.0.0 to 1.2.0 — additive, backwards
compatible with every 1.x renderer.
Overview
The v0.2 alpha line stabilised the publication chain and the runtime error taxonomy. v0.2.0-beta.1 closes the runtime feature gap:
- Cursor-less pagination —
?limit=N&offset=MwithtotalCountecho. - Whitelisted filtering — three operators (
eq,in,contains), parameterised SQL, no nested boolean trees. - Multi-column sorting —
?sort=<field>:<dir>,…with deterministicid ASCtie-breaker.
Every primitive ships with a defence-in-depth column whitelist at the
SQL adapter layer, end-to-end test coverage including SQL-injection
attempts, and a HTTP surface that fails closed with 400 BadRequest
on every malformed input.
Runtime — what's new
Pagination
GET /projections/{fqn}?limit=N&offset=M
limitclamped to[1, 1000], default 50.offsetnon-negative, default 0.- Subject mode (
?subject=…) ignores both. - Wire echo:
data.pagination = {limit, offset, totalCount, pageSize, nextCursor}wherenextCursoris reserved atnullfor the future cursor axis.
Filtering
?filter.<field>.<op>=<value>
Three whitelisted operators:
| Op | Semantics | Value shape |
|---|---|---|
eq | exact scalar match | scalar |
contains | case-insensitive substring (string fields) | scalar, LIKE meta-escaped |
in | membership in a list | comma-separated, ≤ 100 entries |
Refused at construction or at the HTTP layer:
- nested boolean trees, OR groups, arbitrary SQL fragments, regex, dynamic operators;
- unknown field names (against the projection's declared field list);
- malformed query keys (
filter.<field>.<op>shape enforced); - empty
inlists, emptyinentries.
SQL translation uses prepared statements only; LIKE metacharacters in
contains values are escaped so a literal % does not widen the
match. Three classic SQL-injection vectors ('OR 1=1, DROP TABLE,
backslash-escape) are pinned in
apps/playground/filtering-test.php.
Sorting
?sort=<field>:<dir>[,<field>:<dir>]
dirmust be exactlyascordesc(capitalised forms refused).- Multi-column composes in the order declared.
- A deterministic
id ASCtie-breaker is always appended, so pagination over a tied sort key is stable.
ViewSchema wire — 1.2.0
Additive over 1.0.0. A 1.0.0 renderer sees the new keys and ignores
them safely.
{
"schemaVersion": "1.2.0",
"filters": [
{ "field": "status", "op": "eq", "value": "ISSUED" }
],
"sort": [
{ "field": "createdAt", "direction": "desc" }
],
"data": {
"items": [ /* ... */ ],
"pagination": {
"limit": 50,
"offset": 0,
"totalCount": 42,
"pageSize": 42,
"nextCursor": null
}
}
}
Renderer compatibility: @ausus/renderer-react@0.2.0-beta.1 keeps
peerSchemaVersion: ^1.0.0. Every 1.x backend remains consumable.
Developer experience
composer serveon the starter scaffold boots a dev server athttp://localhost:8000via the newpackages/starter/bin/server.php.- The
ausus/standard-stackfacade gainsApplication::renderProjection(string $fqn, ?Reference, int $limit, int $offset, list<Filter>, list<Sort>): arraymirroring the HTTP API defaults — non-HTTP callers can paginate / filter / sort without grabbing the renderer directly.
CI / release engineering
The publication chain hardening from the alpha.5 hotfix is now permanent:
scripts/generate-release-manifest.sh— immutable per-tag JSON manifest committed alongside the release.scripts/archive-release-evidence.sh— every gate log captured per tag underartifacts/releases/<version>/for after-the-fact audit..github/workflows/release-replay.yml—workflow_dispatchworkflow that replays the live release-gate against any published tag, read-only (nogit push, nonpm publish, nogit tag).scripts/release-gate.shStep 4b — renderer npm provenance metadata pre-flight, defeats the BUG-A4-2 class of regressions.scripts/release-gate.shStep 5 — homepage URL HEAD bursts now paced + retry-budgeted; defeats the GitHub HEAD rate-limit intermittency observed in late-alpha.5.scripts/release-gate.shStep 9 — clean-room starter install gate (5 sub-gates A–E).scripts/public-install.shStep 7 — wire shape assertion driven byEXPECTED_SCHEMA_VERSION, defaults to1.2.0forv0.2.0-beta.*.scripts/integration-http.sh— 14 live-trace renderer assertions PLUS 25 live filter+sort HTTP assertions..github/workflows/release-gate.yml— PHP 8.3 + 8.4 matrix.
Installation
The canonical install command for the beta line:
composer create-project "ausus/starter:^0.2@beta" myapp --stability=beta
cd myapp
composer boot
composer serve # → http://localhost:8000
If you previously installed the alpha line with --stability=alpha,
your existing composer.json resolves to v0.2.0-beta.1 automatically
because Composer's @alpha flag accepts beta. No manual constraint
update is required.
Renderer
@ausus/renderer-react@0.2.0-beta.1 is the npm release that pairs
with this backend.
- No TypeScript / build / peer-dependency change.
peerSchemaVersionstays at^1.0.0(covers1.0.0,1.1.0,1.2.0).repository.urlandhomepagecorrectly identify theadonko3xBitters/ausus-frameworkrepo for sigstore provenance.
Known limitations
- Cursor-based pagination is reserved for a future minor — the
data.pagination.nextCursorfield is the placeholder. - Boolean filter trees (nested AND/OR groups) are explicitly out of scope; multiple filter conditions on the same projection AND together but cannot be combined with OR.
- Sort by computed expressions (e.g.
LOWER(name),created_at + interval) is rejected by the column whitelist. - MySQL / PostgreSQL drivers remain post-1.0 work.
scripts/public-install.shstep 7 asserts wire shape against the embedded plugin — adapter-level cursor support will need its own contract pin when the time comes.
Released artifacts
| Package | Version |
|---|---|
ausus/kernel | v0.2.0-beta.1 |
ausus/runtime-default | v0.2.0-beta.1 |
ausus/persistence-sql | v0.2.0-beta.1 |
ausus/api-http | v0.2.0-beta.1 |
ausus/standard-stack | v0.2.0-beta.1 |
ausus/starter | v0.2.0-beta.1 |
ausus/tenancy-row | v0.2.0-beta.1 (name-reserved) |
ausus/audit-database | v0.2.0-beta.1 (name-reserved) |
ausus/auth-bridge | v0.2.0-beta.1 (name-reserved) |
ausus/presentation-default | v0.2.0-beta.1 (name-reserved) |
@ausus/renderer-react | 0.2.0-beta.1 |