Skip to content

feat: collections stage 3 contract and core (RFC-0042 step 1) - #103

Merged
Madraka merged 3 commits into
mainfrom
feat/stage3-contract
Oct 23, 2026
Merged

Madraka merged 3 commits into
mainfrom
feat/stage3-contract

Conversation

@Madraka

@Madraka Madraka commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Step 1 of RFC-0042's rollout (ADR-0044). No behaviour change: nothing reads the new code yet.

Contract

  • CollectionSettings.listFields (≤ 4 keys), expiry ({field, action: unlist|hide, afterMinutes?}) and structuredData ({type, properties}).
  • Each property's source is chosen by kind: field, entry, site or text. EntryValueProperty and SiteValueProperty are named $defs, because cargo-typify merges inline enums.
  • ContentListSection gains where (1–4 FieldConditions) and orderBy (FieldOrder).
  • Fixtures: 4 valid and 44 invalid. TS and Rust are regenerated; Rust emits #[serde(tag = "kind")] enum StructuredDataSource.

@cloudhal/core-ts/structured-data (new subpath)

  • The closed table for Event, JobPosting, Product and Recipe, with no rating or review paths.
  • checkStructuredData: unknown paths and fields, source/type mismatches, vocabularies, ISO 4217 currencies, and required properties (no constants on them).
  • structuredDataFor: no document when a required value is missing. The 32 KB cap drops optional properties first.

@cloudhal/core-ts/fields

  • query.ts: the shared evaluator (parseFieldQuery, matchesFieldQuery, compareByField, checkFieldQuery → invalid_query).
  • gate.ts: fieldGateInstant and expiryInstant, computing min(until, field date + grace). A date ends at the start of the next day in the site's zone, computed with Intl only, never early.
    • It is checked against Temporal on every day of 4 years in 17 zones.
    • One known gap in the oracle: temporal-polyfill misses Casablanca's 2018 Ramadan DST suspension, so that zone-year is checked against Intl instead.

ADR-0044 fix: the constant source kind is text, as in RFC-0042 §1 (the ADR had said constant).

Tests

  • core-contracts: 526.
  • core-ts: 76 new tests (gate 32, query 18, structured data 26). Locally the Miniflare DO tail fails with EADDRNOTAVAIL.
  • cargo test and clippy pass.
  • Packaging, size check and no drift pass.

Changeset: minor (core-contracts, core-ts).

🤖 Generated with Claude Code

Madraka and others added 3 commits October 23, 2026 11:06
…042 step 1)

- Contract: CollectionSettings.listFields, expiry and structuredData
  (sources by kind: field, entry, site, text; EntryValueProperty and
  SiteValueProperty as named $defs), contentList where/orderBy
  (FieldCondition, FieldOrder); 4 valid and 44 invalid fixtures; TS and
  Rust regenerated.
- @cloudhal/core-ts/structured-data: the closed table for Event,
  JobPosting, Product and Recipe, checkStructuredData,
  structuredDataFor (required values, vocabularies, ISO 4217, 32 KB).
- @cloudhal/core-ts/fields: the shared query evaluator (query.ts) and
  fieldGateInstant / expiryInstant (gate.ts, Intl only), with an oracle
  test against Temporal across 17 zones.
- ADR-0044: the constant source kind is `text`, as in RFC-0042 §1.

No behaviour change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
`text` named the value's type while `field`, `entry` and `site` name
its origin, and `text` is already a field type (RFC-0041). `constant`
matches the other kinds, the prior art (R2RML rr:constant, JSON Schema
const) and leaves room for typed constants later. Decided by Halil
before release; RFC-0042 §1 and ADR-0044 updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
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