feat: scaffold deployment-policies monorepo
OPA/Rego deployment gateway policies: 5 rules (valid-environment, require-approvals, no-self-approval, block-weekends, freeze-window), a deploy-gate combining them, JSON schemas, scenario-driven tests, Gitea Actions CI (verify + publish to generic registry), changesets versioning, Makefile and scripts.
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# Tech Stack
|
||||
|
||||
## Overview
|
||||
|
||||
| Layer | Technology | Version | Purpose |
|
||||
| --------------- | ---------- | ------- | ------- |
|
||||
| Policy language | Rego | OPA 1.x (`rego.v1`) | Authoring deployment-gateway policy rules and gates |
|
||||
| Policy engine | OPA | `v1.20.2` (pinned) | Evaluating, testing, type-checking and bundling the policies |
|
||||
| Policy linter | regal | `v0.42.0` | Static linting of Rego best practices (optional in CI) |
|
||||
| Bundles | OPA bundle format | — | Distributable `.tar.gz` bundles (rule modules at `data.rules.*`) |
|
||||
| Schemas | JSON Schema (draft 2020-12) | — | Static validation of `input` and `data` via `opa check --schema` |
|
||||
| Versioning | Changesets | `@changesets/cli@3.0.3` | Tracking per-policy version bumps across npm workspaces |
|
||||
| Changelog formatting | oxfmt | `^0.68.0` | Formatting generated changelogs/changesets via `format: "oxfmt"` |
|
||||
| Package management | npm workspaces | npm 11 / Node 24 | Monorepo layout (`policies/rules/*`, `policies/gates/*`) |
|
||||
| CI/CD | Gitea Actions | Gitea 1.27.0 | Verify, test, build and publish on `main` |
|
||||
| Package registry| Gitea generic registry | — | Storing published rule/gate bundles |
|
||||
| Build tooling | GNU make + bash | — | `Makefile` targets wrapping the scripts |
|
||||
| Hosting | Gitea self-hosted | `1.27.0` | Source control, CI runners, package registry (gitea.devegamoreno.com) |
|
||||
|
||||
## Justification
|
||||
|
||||
- **OPA + Rego**: standard, policy-as-code engine for authorization/gating; bundles are the
|
||||
portable distribution unit; binary CLI avoids container runtime requirements.
|
||||
- **Pinned OPA `v1.20.2`**: reproducible engine version locally and in CI via `scripts/install-opa.sh`
|
||||
(no Docker), so tests and `opa build` see identical behaviour everywhere.
|
||||
- **`rego.v1`**: canonical OPA 1.x syntax (import of `rego.v1`), future-proof and unambiguous.
|
||||
- **Per-rule JSON Schemas**: `opa check --strict --schema` catches input/data type mistakes at
|
||||
authoring time instead of runtime.
|
||||
- **Separate evaluation / small rules**: each rule is an independent package+bundle with a small,
|
||||
testable contract; consumers combine the results at runtime, enabling reuse across gates.
|
||||
- **Changesets over npm workspaces**: each rule/gate is an npm package solely for versioning;
|
||||
changesets links repository-level changes to published registry versions. `oxfmt` is used only
|
||||
to format changelog markdown (there is no `prettier-plugin-rego` on npm), while Rego formatting
|
||||
is enforced by `opa fmt` in CI.
|
||||
- **Gitea generic registry**: stores arbitrary files (`.tar.gz` bundles) under
|
||||
`/api/packages/{owner}/generic/{package}/{version}/{file}` without adding an external registry
|
||||
dependency.
|
||||
- **npm workspaces** (over pnpm/yarn): zero extra tooling; changesets v3 requires Node ≥ 22.11 and
|
||||
npm ≥ 10.9, both met.
|
||||
|
||||
## Tools not used (and why)
|
||||
|
||||
- **Docker/containers**: excluded by design; OPA ships a static binary, so containers add
|
||||
unnecessary runtime complexity for tests, checks and bundle builds.
|
||||
- **prettier-plugin-rego**: does not exist on npm (verified 404); Rego formatting is
|
||||
instead owned by `opa fmt`.
|
||||
- **pnpm/yarn**: changesets supports them, but npm workspaces suffice since these packages are
|
||||
private versioning shims, not published JS packages.
|
||||
|
||||
## Integration points
|
||||
|
||||
- **Gitea Actions** reads `secrets.GITEA_TOKEN` (scope `write:package`) and
|
||||
`GITEA_OWNER`/`GITEA_URL`; publish job runs only on `main`.
|
||||
- **`scripts/publish.sh`** uploads via `curl` to the generic registry; package names are
|
||||
prefixed `rule-*` and `gate-*`.
|
||||
- **Consumer contract**: bundles scope roots to `rules` so operators can supply
|
||||
`data.deploygate.*` configuration separately and still have static schema checks apply.
|
||||
|
||||
## Environment (local dev machine)
|
||||
|
||||
- macOS (darwin/arm64), zsh
|
||||
- Node.js `v24.18.0`, npm `11.16.0`
|
||||
- git `2.50.1`, GNU make
|
||||
- `tools/opa` (OPA `v1.20.2` binary committed to the repo working tree via install script, not git)
|
||||
- regal `v0.42.0` optional on `PATH`
|
||||
Reference in New Issue
Block a user