diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f09a816 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: Documentation +on: + push: + branches: [main] + pull_request: + branches: [main] +permissions: + contents: read +jobs: + documentation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24 + - name: Lint Markdown + run: npx --yes markdownlint-cli2@0.23.2 --config .markdownlint.json '**/*.md' + - name: Check local document and asset links + run: | + node --input-type=module <<'JS' + import fs from 'node:fs'; + import path from 'node:path'; + function check(directory) { + for (const entry of fs.readdirSync(directory, { withFileTypes: true })) { + if (entry.name === '.git') continue; + const file = path.join(directory, entry.name); + if (entry.isDirectory()) { check(file); continue; } + if (!file.endsWith('.md')) continue; + const text = fs.readFileSync(file, 'utf8'); + for (const match of text.matchAll(/\]\(([^)]+)\)|src="([^"]+)"/g)) { + const link = match[1] ?? match[2]; + if (link.includes('://') || link.startsWith('#')) continue; + const target = path.resolve(path.dirname(file), link.split('#')[0]); + if (!fs.existsSync(target)) throw new Error(`${file}: missing ${link}`); + } + } + } + check('.'); + JS diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..6092ee1 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,10 @@ +{ + "default": true, + "MD013": { + "line_length": 120, + "tables": false, + "code_blocks": false + }, + "MD033": false, + "MD041": false +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..e9af489 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,15 @@ +# Organization repository guidelines + +Treetop is in early release. Across every project repository, prioritize +correctness, explicit ownership, and strict uniform contracts over compatibility. +Remove obsolete aliases and defaults deliberately; document breaking changes and +concrete consumer migrations in the repository changelog and organization guide. + +Keep the full project catalog, planned versions, PR links, and release order in +sync. Distinguish unpublished candidates from available releases. Use immutable +source/action pins for coordinated verification and never claim unrun checks pass. + +This repository owns organization documentation and branding. Preserve unrelated +assets. Lint Markdown and check relative links. Prefer primary project sources for +claims. Do not send external announcements, merge, tag, or publish without explicit +user approval. Signed commits and squash merges are required for project changes. diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000..b53334d --- /dev/null +++ b/Changelog.md @@ -0,0 +1,11 @@ +# Changelog + +## 2026-09-06 + +- Announce the coordinated breaking release with declared tuple ownership, + format 2 bundles, strict current consumer contracts, and explicit release order. +- Establish correctness over compatibility as the policy across every early-release + repository. Add the Go client to the complete project catalog. +- Link the merged implementation PRs and published releases. Record verified + registry dependencies, immutable REST pins, and the released Bundle Action v2. +- Enforce Markdown and local document/asset links in a minimal read-only CI job. diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 0000000..6d25818 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,105 @@ +# Coordinated breaking release: declared label targets + +Released 2026-09-06 after coordinated review and verification. This document is +the organization announcement, breaking migration guide, and upgrade order. + +Early Treetop releases prioritize correctness over compatibility across every +repository. Breaking changes must be intentional, tested, announced, and supplied +with concrete migration steps. Remove obsolete aliases and defaults instead of +preserving ambiguous behavior behind compatibility layers. + +## One owner per declared tuple + +Label ownership is `(fully qualified Cedar resource type, attribute name)`. +`App::Host.labels` and `Other::Host.labels` are independent. Two rules cannot own +`App::Host.labels`; combine their patterns under one declaration or rename an +output. A root type such as `Host` is exact, not a wildcard or an alias for every +namespaced Host. + +```json +{ + "target": {"resource_type": "App::Host", "attribute": "labels"}, + "field": "name", + "patterns": [{"name": "prod", "regex": "^prod"}] +} +``` + +Replace old `kind` and `output` fields with this target. Labelers declare a +validated `LabelTarget` and implement read-only `derive`; `applies_to` and `output` +are removed. Receiver-style `LabelerApply::apply` owns mutation. Core freezes +ownership at registration, rejects duplicate tuples and reserved `id`, matches +exact resource types, and clears every owned attribute on that type before any +rule derives its output. Repeated applications replace or remove owned values. + +Scoping includes sanitation. An `App::Host` owner does not clear attributes on +`Other::Host`. Policies must constrain the actual resource type before trusting a +derived attribute. Bundle delegates runtime application to Core; clients and the +workbench consume the server contract and do not implement policy evaluation. + +## Required consumer updates + +| Repository | Release | Review | Required update | +| --- | --- | --- | --- | +| Core | [0.1.0](https://crates.io/crates/treetop-core/0.1.0) | [PR #60](https://github.com/treetop-policy-engine/treetop-core/pull/60) | Implement `target` and `derive`, use validated targets, remove deprecated listing aliases | +| Bundle | [0.1.0](https://github.com/treetop-policy-engine/treetop-bundle/releases/tag/v0.1.0) | [PR #10](https://github.com/treetop-policy-engine/treetop-bundle/pull/10) | Declare targets, adopt format 2, rebuild and re-sign archives | +| REST | [0.1.0](https://github.com/treetop-policy-engine/treetop-rest/releases/tag/v0.1.0) | [PR #73](https://github.com/treetop-policy-engine/treetop-rest/pull/73) | Deploy new configurations and archives; adopt current endpoints and metadata | +| Rust SDK | [0.1.0](https://crates.io/crates/treetop-client/0.1.0) | [PR #15](https://github.com/treetop-policy-engine/treetop-client/pull/15) | Remove deprecated constructors/health alias; use required metadata and separate schema revisions | +| CLI | [0.1.0](https://github.com/treetop-policy-engine/treetop-cli/releases/tag/v0.1.0) | [PR #9](https://github.com/treetop-policy-engine/treetop-cli/pull/9) | Upgrade the SDK/server pair and remove legacy response assumptions | +| Python | [0.1.0](https://pypi.org/project/treetop-client/0.1.0/) | [PR #13](https://github.com/treetop-policy-engine/treetop-client-python/pull/13) | Use uniform batch methods, canonical decisions, required metadata, and complete response correspondence | +| Go | [0.3.0](https://pkg.go.dev/github.com/treetop-policy-engine/treetop-client-go@v0.3.0) | [PR #4](https://github.com/treetop-policy-engine/treetop-client-go/pull/4) | Use current metadata, `Live`/`Ready`, and distinct schema revision types | +| Frontend | [0.1.0](https://github.com/treetop-policy-engine/treetop-frontend/releases/tag/v0.1.0) | [PR #4](https://github.com/treetop-policy-engine/treetop-frontend/pull/4) | Use exact target fields and strict generated/current responses; rebuild demos | +| Bundle Action | [2.0.0 / v2](https://github.com/treetop-policy-engine/treetop-bundle-action/releases/tag/v2.0.0) | [PR #8](https://github.com/treetop-policy-engine/treetop-bundle-action/pull/8) | Require CLI 0.1.0, format 2, and exact checksum asset names | +| Organization | Documentation | This announcement | Adopt the shared early-release correctness policy and rollout guidance | + +Bundle and module manifests now require `format_version = 2`. Old manifests, +archives, signatures over old archives, and old label syntax are not migrated +implicitly. Update sources, rebuild, review diagnostics, and re-sign new bytes. +Failed reloads leave the previous complete authorization generation active. + +Use `/livez`, `/readyz`, and `/openapi.json`; the legacy health and OpenAPI aliases +are removed. Policy versions require `hash`, `loaded_at`, nullable `label_set`, and +unsigned 64-bit `generation`. Generation is local to an engine instance. Schema +revisions are separate hash/timestamp objects. Status includes schema metadata, +request limits, and context capabilities. An explicit zero limit never means +unlimited. JavaScript rejects integers it cannot represent exactly. + +Use authorization evaluation as the source of truth. Candidate policy listings +do not execute Cedar conditions and can include forbids; they are never proof of +permission. Clients reject inconsistent batch counts, positions, IDs, versions, +and decision details. Parsing errors must never become allow decisions. + +## Upgrade and release order + +Every consumer uses published prerequisites. Bundle requires Core 0.1.0 from +crates.io; REST requires Core and Bundle 0.1.0; CLI requires Rust SDK 0.1.0. +Temporary Cargo Git patches are removed, with registry checksums in the application +and fuzz lockfiles. Rust SDK, Python, Go, and CLI integration checks pin the REST +release image by digest; the frontend pins its exact released source commit. +Action v2 checks both the released Bundle source and the actual published CLI +assets on every native platform. + +Upgrade in this order: + +1. Core 0.1.0 for embedded Rust applications and custom labeler implementations. +2. Bundle 0.1.0 and its `treetop-bundle` validation CLI, updated format 2 sources, + and rebuilt/re-signed archives. +3. REST 0.1.0 with the new configuration and archive contract. +4. Rust SDK/Python 0.1.0 and Go 0.3.0 against the released REST contract. +5. `treetop-cli`/Workbench 0.1.0 and Bundle Action v2 after their prerequisites are + available. + +The coordinated PRs are squash-merged in dependency order. Release tags point to +verified main commits; package archives and runtime artifacts are checked before +downstream publication. Future releases must preserve substantive migration notes, +keep immutable tags fixed, and pass performance/security checks. + +## Performance considerations + +Declared Cedar types are parsed and validated during construction/reload, not +on each evaluation. Core's new cold target parsing cost is reported separately +from registration and evaluation; benchmark boundaries must stay explicit. +Go's required-field validation currently adds about 4–5% to local response-parse +medians while retaining allocation counts. Python reports no CodSpeed regressions, +but earlier comparisons included an environment warning, so the reported +improvement is not treated as a controlled performance measurement. Each implementation PR +contains its verification evidence and limitations. diff --git a/README.md b/README.md index 3da19b7..1c5f917 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Treetop is an open-source authorization stack built on [Cedar](https://cedarpolicy.com/). It separates access-control policy from application code and provides a consistent path from authoring and validation to deployment, evaluation, and operations. -Most applications use Treetop through the standalone REST service. Official Rust and Python +Most applications use Treetop through the standalone REST service. Official Rust, Go, and Python clients, a command-line client, and a browser workbench cover integration and day-to-day operation. The Rust engine powers the service and remains available for specialized deployments that require in-process evaluation. @@ -17,7 +17,7 @@ in-process evaluation. - Make fine-grained authorization explicit, testable, and independent of application business logic. -- Make centralized authorization straightforward to deploy and consume through a stable REST API +- Make centralized authorization straightforward to deploy and consume through a strict REST API and typed clients. - Retain an embeddable Rust engine for specialized applications that need in-process evaluation. - Package independently owned policy modules into deterministic, verifiable release artifacts. @@ -38,7 +38,7 @@ The wider toolchain provides: - optional Ed25519 signing and verification of policy bundles; - atomic bundle loading in the REST server; - authorization, policy, schema, bundle, OpenAPI, and metrics endpoints; -- typed Rust and Python integrations; +- typed Rust, Go, and Python integrations; - native command-line tools for authorization and bundle workflows; - a browser workbench for requests, policies, schemas, server status, and metrics; and - a GitHub Action for policy validation and unsigned bundle builds in CI. @@ -58,6 +58,18 @@ Cedar policies, schemas, and labels Specialized Rust applications can use `treetop-core` directly when a separate service is not the right deployment model. +## Coordinated breaking release + +The coordinated release adopts declared label ownership by exact Cedar resource type +and attribute. Early Treetop releases prioritize correctness over compatibility; +ambiguous ownership, deprecated aliases, and old-format defaults are removed. +Bundle/module format 2 requires rebuilt and re-signed archives. + +Core, Bundle, REST, Rust/Python clients, CLI, and Workbench are released as 0.1.0; +the Go client is 0.3.0 and Bundle Action is v2. See the +[breaking migration and release set](./MIGRATION.md) for the new syntax, required consumer +updates, published artifacts, and upgrade order. + ## Projects All repositories below are maintained parts of the Treetop project. Together they provide the REST @@ -68,6 +80,7 @@ runtime, policy engine and delivery pipeline, client integrations, and operator | [treetop-rest](https://github.com/treetop-policy-engine/treetop-rest) | Standalone authorization server and REST API | | [treetop-client](https://github.com/treetop-policy-engine/treetop-client) | Typed asynchronous Rust client | | [treetop-client-python](https://github.com/treetop-policy-engine/treetop-client-python) | Typed synchronous and asynchronous Python client | +| [treetop-client-go](https://github.com/treetop-policy-engine/treetop-client-go) | Typed Go client with validated requests and responses | | [treetop-cli](https://github.com/treetop-policy-engine/treetop-cli) | Command-line client and interactive REPL | | [treetop-frontend](https://github.com/treetop-policy-engine/treetop-frontend) | Browser workbench for Treetop servers | | [treetop-bundle](https://github.com/treetop-policy-engine/treetop-bundle) | Policy validation, composition, signing, and archive tooling | @@ -85,5 +98,6 @@ This repository publishes organization-wide GitHub content: When updating the profile, keep the project catalog aligned with the organization's public repositories and published artifacts. Prefer durable links such as `/releases/latest`, registry -project pages, GHCR package pages, and moving major tags for GitHub Actions. Use relative asset paths +project pages, GHCR package pages, and reviewed immutable commits for GitHub Actions. Mark planned artifacts as +unreleased instead of linking to tags that do not exist. Use relative asset paths and verify Markdown links before publishing changes. diff --git a/profile/README.md b/profile/README.md index 86853f6..cc2ead0 100644 --- a/profile/README.md +++ b/profile/README.md @@ -11,6 +11,18 @@ Run Treetop as a REST service, integrate through an official client, compose det bundles, or inspect the service from the command line and browser workbench. The Rust engine can also be embedded for specialized use cases. +## Coordinated breaking release + +The coordinated release adopts declared label ownership by exact Cedar resource type +and attribute. Early Treetop releases prioritize correctness over compatibility; +ambiguous ownership, deprecated aliases, and old-format defaults are removed. +Bundle/module format 2 requires rebuilt and re-signed archives. + +Core, Bundle, REST, Rust/Python clients, CLI, and Workbench are released as 0.1.0; +the Go client is 0.3.0 and Bundle Action is v2. See the +[breaking migration and release set](../MIGRATION.md) for the new syntax, required consumer +updates, published artifacts, and upgrade order. + ## Projects These repositories are all maintained parts of Treetop, covering the runtime, policy delivery, @@ -21,10 +33,11 @@ client integrations, and operator tooling. | [treetop-rest](https://github.com/treetop-policy-engine/treetop-rest) | REST API and standalone server | [server archives](https://github.com/treetop-policy-engine/treetop-rest/releases/latest) · [container](https://github.com/treetop-policy-engine/treetop-rest/pkgs/container/treetop-rest) | | [treetop-client](https://github.com/treetop-policy-engine/treetop-client) | Typed asynchronous Rust client | [crate](https://crates.io/crates/treetop-client) · [docs](https://docs.rs/treetop-client) | | [treetop-client-python](https://github.com/treetop-policy-engine/treetop-client-python) | Typed synchronous and asynchronous Python client | [PyPI](https://pypi.org/project/treetop-client/) | +| [treetop-client-go](https://github.com/treetop-policy-engine/treetop-client-go) | Typed Go client | [Go package](https://pkg.go.dev/github.com/treetop-policy-engine/treetop-client-go) | | [treetop-cli](https://github.com/treetop-policy-engine/treetop-cli) | Command-line client and interactive REPL | [native archives and checksums](https://github.com/treetop-policy-engine/treetop-cli/releases/latest) | | [treetop-frontend](https://github.com/treetop-policy-engine/treetop-frontend) | Browser workbench for policies, requests, and metrics | [static archive and checksum](https://github.com/treetop-policy-engine/treetop-frontend/releases/latest) · [container](https://github.com/treetop-policy-engine/treetop-frontend/pkgs/container/treetop-frontend) | | [treetop-bundle](https://github.com/treetop-policy-engine/treetop-bundle) | Deterministic, optionally signed Cedar policy bundles | [crate](https://crates.io/crates/treetop-bundle) · [docs](https://docs.rs/treetop-bundle) · [CLI archives](https://github.com/treetop-policy-engine/treetop-bundle/releases/latest) | -| [treetop-bundle-action](https://github.com/treetop-policy-engine/treetop-bundle-action) | Policy validation and bundle builds in GitHub Actions | [`@v1` Action](https://github.com/treetop-policy-engine/treetop-bundle-action/tree/v1) · [releases](https://github.com/treetop-policy-engine/treetop-bundle-action/releases) | +| [treetop-bundle-action](https://github.com/treetop-policy-engine/treetop-bundle-action) | Policy validation and bundle builds in GitHub Actions | [v2.0.0](https://github.com/treetop-policy-engine/treetop-bundle-action/releases/tag/v2.0.0) · [releases](https://github.com/treetop-policy-engine/treetop-bundle-action/releases) | | [treetop-core](https://github.com/treetop-policy-engine/treetop-core) | Rust engine underlying Treetop REST, also available for in-process deployments | [crate](https://crates.io/crates/treetop-core) · [docs](https://docs.rs/treetop-core) | ## Release artifacts @@ -35,8 +48,8 @@ client integrations, and operator tooling. | Treetop CLI | Linux x86-64 and ARM64 musl, Apple-silicon macOS, and Windows x86-64 archives with SHA-256 checksums | | Bundle CLI | Linux x86-64 and ARM64 musl, Apple-silicon macOS, and Windows x86-64 archives with `SHA256SUMS` | | Workbench | Versioned static-site archive with a SHA-256 checksum; Linux AMD64 and ARM64 container image | -| Libraries and clients | Rust crates on crates.io and the Python client on PyPI | -| Bundle Action | Versioned GitHub Action, available through the moving `v1` major tag | +| Libraries and clients | Rust crates, Python on PyPI, and versioned Go modules | +| Bundle Action | Versioned GitHub Action; v2.0.0 with the v2 major tag | ## Quick start @@ -54,14 +67,10 @@ Then check process liveness: curl http://127.0.0.1:9999/livez ``` -Validate a policy bundle in GitHub Actions: - -```yaml -- uses: treetop-policy-engine/treetop-bundle-action@v1 - with: - manifest: treetop-bundle.toml - deny-warnings: true -``` +The [action v2 migration](https://github.com/treetop-policy-engine/treetop-bundle-action/blob/v2.0.0/MIGRATION.md) +explains declared-target syntax and format 2 archives. Action v2 downloads the +published Bundle CLI 0.1.0 and verifies its checksum. Pin the reviewed immutable +action release commit in protected policy workflows. -Project-specific documentation, examples, compatibility information, and release notes live in +Project-specific documentation, examples, current contracts, and release notes live in each repository.