Skip to main content

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=M with totalCount echo.
  • Whitelisted filtering — three operators (eq, in, contains), parameterised SQL, no nested boolean trees.
  • Multi-column sorting?sort=<field>:<dir>,… with deterministic id ASC tie-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
  • limit clamped to [1, 1000], default 50.
  • offset non-negative, default 0.
  • Subject mode (?subject=…) ignores both.
  • Wire echo: data.pagination = {limit, offset, totalCount, pageSize, nextCursor} where nextCursor is reserved at null for the future cursor axis.

Filtering

?filter.<field>.<op>=<value>

Three whitelisted operators:

OpSemanticsValue shape
eqexact scalar matchscalar
containscase-insensitive substring (string fields)scalar, LIKE meta-escaped
inmembership in a listcomma-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 in lists, empty in entries.

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>]
  • dir must be exactly asc or desc (capitalised forms refused).
  • Multi-column composes in the order declared.
  • A deterministic id ASC tie-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 serve on the starter scaffold boots a dev server at http://localhost:8000 via the new packages/starter/bin/server.php.
  • The ausus/standard-stack facade gains Application::renderProjection(string $fqn, ?Reference, int $limit, int $offset, list<Filter>, list<Sort>): array mirroring 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 under artifacts/releases/<version>/ for after-the-fact audit.
  • .github/workflows/release-replay.ymlworkflow_dispatch workflow that replays the live release-gate against any published tag, read-only (no git push, no npm publish, no git tag).
  • scripts/release-gate.sh Step 4b — renderer npm provenance metadata pre-flight, defeats the BUG-A4-2 class of regressions.
  • scripts/release-gate.sh Step 5 — homepage URL HEAD bursts now paced + retry-budgeted; defeats the GitHub HEAD rate-limit intermittency observed in late-alpha.5.
  • scripts/release-gate.sh Step 9 — clean-room starter install gate (5 sub-gates A–E).
  • scripts/public-install.sh Step 7 — wire shape assertion driven by EXPECTED_SCHEMA_VERSION, defaults to 1.2.0 for v0.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.
  • peerSchemaVersion stays at ^1.0.0 (covers 1.0.0, 1.1.0, 1.2.0).
  • repository.url and homepage correctly identify the adonko3xBitters/ausus-framework repo for sigstore provenance.

Known limitations

  • Cursor-based pagination is reserved for a future minor — the data.pagination.nextCursor field 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.sh step 7 asserts wire shape against the embedded plugin — adapter-level cursor support will need its own contract pin when the time comes.

Released artifacts

PackageVersion
ausus/kernelv0.2.0-beta.1
ausus/runtime-defaultv0.2.0-beta.1
ausus/persistence-sqlv0.2.0-beta.1
ausus/api-httpv0.2.0-beta.1
ausus/standard-stackv0.2.0-beta.1
ausus/starterv0.2.0-beta.1
ausus/tenancy-rowv0.2.0-beta.1 (name-reserved)
ausus/audit-databasev0.2.0-beta.1 (name-reserved)
ausus/auth-bridgev0.2.0-beta.1 (name-reserved)
ausus/presentation-defaultv0.2.0-beta.1 (name-reserved)
@ausus/renderer-react0.2.0-beta.1