Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions .agents/context/schema-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ All changes are **breaking**. Per project policy (no backward compat pre-product
### Final top-level shape (v0.1.0)

```yaml
# yaml-language-server: $schema=https://schemas.opendecree.dev/schema/v0.1.0/decree.json
# yaml-language-server: $schema=https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json

spec_version: v1 # required, const "v1" (the decree format version)
$schema: https://schemas.opendecree.dev/schema/v0.1.0/decree.json # optional
$schema: https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json # optional
$id: urn:decree:schema:payments:v3 # optional
name: payments # required, slug ^[a-z0-9]([a-z0-9-]*[a-z0-9])?$
description: Payments service config # optional
Expand Down Expand Up @@ -140,22 +140,30 @@ Meta-schema encodes this via `allOf` with 4 `if/then` branches keyed on `type`.

- **Canonical filenames:** `decree.schema.yaml`, `decree.config.yaml`
- **Generic globs:** `*.decree.schema.yaml`, `*.decree.config.yaml` (for repos with multiple schemas)
- **Modeline:** `# yaml-language-server: $schema=https://schemas.opendecree.dev/schema/v0.1.0/decree.json` on line 1 of every example
- **Modeline:** `# yaml-language-server: $schema=https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json` on line 1 of every `*.decree.schema.yaml`; use `decree-config.json` on `*.decree.config.yaml`
- **CLI stays filename-agnostic** — `decree apply some-other-name.yaml` must keep working. The convention drives editor discovery only.

## Publishing

- **URL pattern:** `https://schemas.opendecree.dev/schema/v{MAJOR}.{MINOR}.{PATCH}/decree.json`
- **URL pattern:** two files per version:
- `https://schemas.opendecree.dev/schema/v{MAJOR}.{MINOR}.{PATCH}/decree-schema.json` — validates `*.decree.schema.yaml`
- `https://schemas.opendecree.dev/schema/v{MAJOR}.{MINOR}.{PATCH}/decree-config.json` — validates `*.decree.config.yaml`
- **Pre-stable:** full SemVer in path (`/v0.1.0/`)
- **Post-1.0.0:** switch to major-only paths (`/v1/`) with permanent redirects from historical full-SemVer URLs
- **Hosting:** TBD (GitHub Pages on a dedicated repo, or static-hosted redirect to raw GitHub content). Must be HTTPS, stable, `Content-Type: application/schema+json`.
- **schemastore.org:** PR against `SchemaStore/schemastore` adding entry to `src/api/json/catalog.json`:
- **Hosting:** GitHub Pages on the `opendecree/decree` repo (custom domain `schemas.opendecree.dev` via Cloudflare CNAME, DNS-only). The Pages workflow deploys an explicitly-built `_site/` artifact, so only the `schema/v*/...` files are served; the rest of the repo is not exposed. Content-Type is `application/json` (the issue accepts this as fallback for `application/schema+json`); CORS allows cross-origin (`access-control-allow-origin: *` is the GitHub Pages default for static files). May extract to a dedicated repo if decree's Pages slot is needed for other content.
- **schemastore.org:** PR against `SchemaStore/schemastore` adding **two entries** to `src/api/json/catalog.json`:
```json
{
"name": "OpenDecree Schema",
"description": "OpenDecree configuration schema",
"description": "OpenDecree schema definition (opendecree.dev)",
"fileMatch": ["decree.schema.yaml", "decree.schema.yml", "*.decree.schema.yaml", "*.decree.schema.yml"],
"url": "https://schemas.opendecree.dev/schema/v0.1.0/decree.json"
"url": "https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json"
},
{
"name": "OpenDecree Config",
"description": "OpenDecree configuration values (opendecree.dev)",
"fileMatch": ["decree.config.yaml", "decree.config.yml", "*.decree.config.yaml", "*.decree.config.yml"],
"url": "https://schemas.opendecree.dev/schema/v0.1.0/decree-config.json"
}
```

Expand Down Expand Up @@ -191,7 +199,7 @@ Meta-schema encodes this via `allOf` with 4 `if/then` branches keyed on `type`.

### Phase C — Publishing

- #125 — Host meta-schema at `https://schemas.opendecree.dev/schema/v0.1.0/decree.json`
- #125 — Host meta-schemas at `https://schemas.opendecree.dev/schema/v0.1.0/decree-{schema,config}.json`
- #126 — Submit schemastore.org PR

### Phase D — Docs
Expand Down
2 changes: 1 addition & 1 deletion internal/schema/yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const (
yamlSpecVersionV1 = "v1"
// metaSchemaURL is the canonical URL of the meta-schema that validates
// decree.schema.yaml documents at this spec version. Emitted on export.
metaSchemaURL = "https://schemas.opendecree.dev/schema/v0.1.0/decree.json"
metaSchemaURL = "https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json"
)

// schemaURNPattern matches decree schema URNs: urn:decree:schema:<segment>(:<segment>)*
Expand Down
4 changes: 2 additions & 2 deletions internal/schema/yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,9 @@ func TestYAMLValidation_SchemaAndID(t *testing.T) {
})

t.Run("both accepted when well-formed", func(t *testing.T) {
doc, err := unmarshalSchemaYAML([]byte("spec_version: \"v1\"\n$schema: https://schemas.opendecree.dev/schema/v0.1.0/decree.json\n$id: urn:decree:schema:test:v1" + validBody))
doc, err := unmarshalSchemaYAML([]byte("spec_version: \"v1\"\n$schema: https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json\n$id: urn:decree:schema:test:v1" + validBody))
require.NoError(t, err)
assert.Equal(t, "https://schemas.opendecree.dev/schema/v0.1.0/decree.json", doc.Schema)
assert.Equal(t, "https://schemas.opendecree.dev/schema/v0.1.0/decree-schema.json", doc.Schema)
assert.Equal(t, "urn:decree:schema:test:v1", doc.ID)
})

Expand Down
Loading