diff --git a/AGENTS.md b/AGENTS.md index f4dc36e..3132213 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -136,6 +136,15 @@ If Regal flags an issue, look it up in the [Regal rule catalog](https://docs.sty Each framework lives under `v1/`. When the upstream regulation changes materially, add `v2/` alongside — don't mutate `v1/` in place. See [COMPATIBILITY.md](COMPATIBILITY.md). +## Diagrams and visual assets + +All README diagrams live in [`diagrams/`](diagrams/) as paired **light and dark SVGs**, embedded via `` for GitHub theme switching. The full design system (palette, type, shape language, naming, contribution flow) is documented in [`diagrams/STYLE.md`](diagrams/STYLE.md). Read it before adding or modifying any diagram. + +- **Edit existing diagrams in place** — they are hand-authored SVGs, not generated. Open the file, change it, validate with `python3 -c "import xml.etree.ElementTree as ET; ET.parse('')"`. +- **Do not reintroduce a matplotlib generator** — the previous `generate_diagrams.py` was deliberately removed. Hand-authored SVGs are the source of truth. +- **New diagrams must ship both `_light.svg` and `_dark.svg` variants.** Use `` markup; verify GitHub theme switching by viewing the rendered README on both light and dark settings. +- **Rego syntax-coloured text** in `diagram3_policy_anatomy` uses `` with `xml:space="preserve"` on the parent — without that attribute Inkscape and some browsers normalise whitespace and keywords run into the next token. + ## What NOT to do - Don't edit policies under `custom/` — that's a local-only space for downstream consumers. diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aab621..5087efa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,15 +8,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added -- Centered HTML hero, ordered badge wall, three big-number value-prop cards, and 5 programmatically-generated marketing diagrams in the README (hero numbers, directory tree, policy anatomy, framework grid, evaluation flow). -- `AGENTS.md` and `CLAUDE.md` — operational instructions for AI coding agents working in this repository. `GEMINI.md` refreshed to inherit from `AGENTS.md` while preserving the author's working principles. -- `skills/` directory with 3 Claude Code skills: `draft-rego-policy`, `explain-framework`, `add-framework`. Each ships as a slash command once installed into `~/.claude/skills/`. -- Comparison table vs generic OPA bundles and vendor governance SaaS in the README. -- `diagrams/generate_diagrams.py` — reproducible matplotlib script that regenerates every marketing PNG. +- **Hand-authored, theme-aware SVG diagrams** under [`diagrams/`](diagrams/) — paired `_light.svg` + `_dark.svg` for hero banner, hero numbers, directory tree, policy anatomy, and evaluation flow. Embedded via `` so GitHub light- and dark-theme readers each see the matching variant. +- **Brand assets** — standalone `logo_{light,dark}.svg` (hexagon + `{}` curly braces, signalling policy-as-code), `og_card_{light,dark}.svg` + a 1200×630 `og_card.png` for GitHub Settings → Social preview. +- **[`diagrams/STYLE.md`](diagrams/STYLE.md)** — design-system reference (palette, typography, shape language, light/dark pattern, contribution flow) shared with sister project AICertify. +- **[`CONTRIBUTING.md`](CONTRIBUTING.md)** — policy-authoring conventions, local-checks recipe, PR review criteria, and a "adding a new framework" guide. Resolves the broken link the README had been carrying. +- **[`SECURITY.md`](SECURITY.md)** — private vulnerability-disclosure flow at `security@principledevolution.ai`, 5-business-day acknowledgement, coordinated disclosure. Explicitly distinguishes security issues from policy-correctness disputes. +- **`AGENTS.md`** — new "Diagrams and visual assets" section pointing future agents at the SVG system and explicitly retiring the matplotlib generator. +- Previously (still in this Unreleased line): `AGENTS.md`, `CLAUDE.md`, `GEMINI.md` operational instructions for AI coding agents; `skills/` directory with 3 Claude Code skills (`draft-rego-policy`, `explain-framework`, `add-framework`); comparison table vs generic OPA bundles and vendor governance SaaS in the README. ### Changed +- **Top of README** — replaced the `

GOPAL

` + bold tagline with a hero banner SVG that bakes in the wordmark and value prop, tightening the top fold across all 5 language READMEs (en, zh-CN, ja-JP, ko-KR, hi-IN). - README rewritten for product-page clarity: hero numbers, then quick start, then differentiation, then directory map. +### Removed +- **`diagrams/generate_diagrams.py`** — matplotlib generator retired. Hand-authored SVGs are now the source of truth; see [`diagrams/STYLE.md`](diagrams/STYLE.md) for how to add new ones. +- **`diagram4_framework_grid.png`** — the markdown comparison table directly below it does the same job; the embedded image was redundant. + ## [1.0.0] — 2025-07 ### Added diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..dd0827c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,87 @@ +# Contributing to GOPAL + +Thanks for considering a contribution. GOPAL is an open, community-curated library of [OPA](https://www.openpolicyagent.org/) Rego policies encoding AI-governance requirements; the more eyes on each rule, the better the policies get. + +## What we welcome + +- **New policies** for an existing framework (e.g. an additional EU AI Act article) +- **New frameworks** (e.g. UK AI Principles, California SB-1047 successor, MAS banking AI guidance) +- **New industry verticals** (e.g. media, energy, defence) +- **Fixes** for bugs in existing policy logic +- **Tests** — every policy should have a sibling `*_test.rego`. Missing tests on existing policies are open invitations. +- **Translations** — the README ships in 5 languages. Native-speaker review of any of them is gold. +- **Documentation** improvements (CONTRIBUTING, README, AGENTS, STYLE) + +## Before you open a PR + +1. **Open or check an issue first.** For new frameworks or larger additions, a quick "I'm planning to add X" comment avoids duplicate work. +2. **Run the same checks CI runs.** See [Development](#development) below. +3. **Match the existing policy shape.** Every policy file follows the same structure (package, imports, METADATA, default deny, allow rule, report). See [diagrams/diagram3_policy_anatomy_light.svg](diagrams/diagram3_policy_anatomy_light.svg) and any existing `.rego` for the canonical pattern. +4. **Add a test sibling.** A new `foo.rego` needs a `foo_test.rego` covering both allow and deny cases. +5. **Update [CHANGELOG.md](CHANGELOG.md)** under `[Unreleased]` with a one-line entry describing your change. + +## Development + +```bash +# One-time setup +pip install pre-commit +curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64 \ + && chmod +x opa && sudo mv opa /usr/local/bin/ +curl -L -o regal https://github.com/StyraInc/regal/releases/latest/download/regal_Linux_x86_64 \ + && chmod +x regal && sudo mv regal /usr/local/bin/ +pre-commit install + +# Run the checks CI runs +opa check --ignore custom/ . +regal lint --ignore-files custom/ . + +# Run tests for a specific package +opa test international/eu_ai_act/v1/ +``` + +If `opa check` fails it usually means a typo in a package path or an undeclared rule. If `regal lint` fails, run with `--format pretty` for human-readable advice on the issue. + +## Policy authoring conventions + +- **Package path mirrors the directory.** `international/eu_ai_act/v1/transparency.rego` declares `package international.eu_ai_act.v1.transparency`. +- **Default deny.** Every policy starts with `default allow := false` so a missing rule produces a safe (deny) result, never an accidental allow. +- **Metadata comments.** Use `# METADATA` followed by `# title:` and `# description:` so the rule is human-readable in audit reports. +- **Report composition.** Use `data.helper_functions.reporting.compose_report(...)` to produce the standardized output shape — don't roll your own report dict. The helper guarantees the field names auditors expect. +- **Versioning.** New frameworks go under `/v1/`. When a regulation amends, the old `v1/` stays put and a new `v2/` ships alongside. See [COMPATIBILITY.md](COMPATIBILITY.md). +- **Reference data needed?** Add it as a constant inside the policy or under a sibling `_data.rego`. Avoid runtime dependencies on external services. + +## Adding a new framework + +The fastest path: + +1. Decide where it goes: `international/`, `industry_specific/`, `global/`, or `operational/`. +2. `mkdir //v1/` +3. Drop in a first policy that follows the standard shape. The [`draft-rego-policy`](skills/draft-rego-policy/SKILL.md) skill scaffolds this for you under Claude Code. +4. Add a test sibling. +5. Update the README count + add a row under "What's Inside". +6. Open a PR. + +## PR review + +PRs are reviewed for: + +1. **Correctness** — does the policy logic accurately encode the regulation? +2. **Test coverage** — does the test cover both allow and deny? Edge cases? +3. **Style** — `opa check` + `regal lint` clean? Matches existing patterns? +4. **Scope** — single concern per PR, easier to revert. + +We aim to respond within 5 business days. Larger framework additions may take longer if the regulator's text needs verification. + +## Custom policies + +The `custom/` directory is `.gitignore`d and CI-skipped — that's where your organization's proprietary rules go. They evaluate alongside the public set without ever being pushed to this repo. See the [README's Custom Policies section](README.md#custom-policies). + +## Community + +- **Questions** — open a [Discussion](https://github.com/Principled-Evolution/gopal/discussions) or comment on the relevant issue. +- **Security disclosures** — see [SECURITY.md](SECURITY.md). Do not file public issues for vulnerabilities. +- **Code of conduct** — be kind, assume good faith, focus on the work. + +## License + +By contributing, you agree your contributions will be licensed under the [Apache License 2.0](LICENSE), the same license as GOPAL itself. diff --git a/README.hi-IN.md b/README.hi-IN.md index b96914b..2650c3e 100644 --- a/README.hi-IN.md +++ b/README.hi-IN.md @@ -1,4 +1,9 @@ -

GOPAL

+
+ + + GOPAL — The Rego policy library for AI compliance + +

English | @@ -8,10 +13,6 @@ हिन्दी

-

- AI कंप्लायंस के लिए Rego पॉलिसी लाइब्रेरी। -

-

94 पॉलिसीज़। 15+ रेगुलेटरी फ्रेमवर्क्स। 5 इंडस्ट्री वर्टिकल्स। Policy-as-code जिसे आपका ऑडिटर पढ़ सकता है।

@@ -34,13 +35,23 @@ इन्हें अपने AI सिस्टम के metadata, model cards, या मूल्यांकन परिणामों के विरुद्ध चलाइए — और एक संरचित, मशीन-रीडेबल कंप्लायंस वर्डिक्ट प्राप्त कीजिए जिसे आप CI, ऑडिट लॉग, या रेगुलेटर सबमिशन में डाल सकते हैं। -

GOPAL — 94 पॉलिसीज़, 15+ फ्रेमवर्क्स, 5 वर्टिकल्स

+

+ + + GOPAL कवरेज: 94 पॉलिसीज़, इंटरनेशनल स्टैंडर्ड्स, एविएशन, इंडस्ट्री वर्टिकल्स, और क्रॉस-कटिंग सिद्धांत + +

--- ## Quick Start -

GOPAL मूल्यांकन कैसे काम करता है — इनपुट JSON, OPA इंजन, पॉलिसी, वर्डिक्ट

+

+ + + GOPAL मूल्यांकन कैसे काम करता है — इनपुट JSON, Rego पॉलिसी, OPA मूल्यांकन, वर्डिक्ट + +

### OPA CLI के साथ स्टैंडअलोन @@ -90,7 +101,12 @@ GOPAL तीन आयामों में अलग है: ## अंदर क्या है -

GOPAL डायरेक्टरी लेआउट — 5 शीर्ष-स्तरीय शाखाएँ, क्षेत्राधिकार और वर्टिकल के अनुसार व्यवस्थित पॉलिसीज़

+

+ + + GOPAL डायरेक्टरी लेआउट — 4 शीर्ष-स्तरीय शाखाएँ, क्षेत्राधिकार और वर्टिकल के अनुसार व्यवस्थित पॉलिसीज़ + +

``` gopal/ @@ -133,8 +149,6 @@ gopal/ ## तुलना -

GOPAL जिन फ्रेमवर्क्स को कवर करता है — EU AI Act, NIST, FAA, EASA, RTCA और अधिक

- | | GOPAL | जेनेरिक OPA बंडल | वेंडर गवर्नेंस SaaS | |---|---|---|---| | विशेष रूप से AI सिस्टम्स को लक्ष्य करता है | ✅ | ❌ | ✅ | @@ -152,7 +166,12 @@ gopal/ ## पॉलिसीज़ लिखना -

एक GOPAL पॉलिसी की संरचना — package path, imports, metadata, default deny, allow rule, report

+

+ + + एक GOPAL पॉलिसी की संरचना — package path, imports, metadata, default deny, allow rule, report + +

हर पॉलिसी एक ही आकार का अनुसरण करती है: diff --git a/README.ja-JP.md b/README.ja-JP.md index 2029d0c..8283e8f 100644 --- a/README.ja-JP.md +++ b/README.ja-JP.md @@ -1,4 +1,9 @@ -

GOPAL

+
+ + + GOPAL — The Rego policy library for AI compliance + +

English | @@ -8,10 +13,6 @@ हिन्दी

-

- AI コンプライアンスのための Rego ポリシーライブラリ。 -

-

94 ポリシー。15 以上の規制フレームワーク。5 つの業種別領域。監査人が読めるポリシー・アズ・コード。

@@ -34,13 +35,23 @@ AI システムのメタデータ、モデルカード、評価結果に対してこれらのポリシーを実行すると、構造化された機械可読のコンプライアンス判定が得られます。CI、監査ログ、規制当局への提出資料にそのまま組み込めます。 -

GOPAL — 94 ポリシー、15 以上のフレームワーク、5 つの業種

+

+ + + GOPAL のカバレッジ: 94 ポリシー、国際規格、航空、業種別、共通原則の 4 カテゴリ + +

--- ## クイックスタート -

GOPAL の評価フロー — 入力 JSON、OPA エンジン、ポリシー、判定

+

+ + + GOPAL の評価フロー — 入力 JSON、Rego ポリシー、OPA 評価、判定 + +

### OPA CLI で単体利用する @@ -90,7 +101,12 @@ GOPAL は次の 3 点で異なります。 ## 同梱内容 -

GOPAL のディレクトリ構成 — 5 つのトップレベル分岐、管轄区域と業種ごとに整理されたポリシー

+

+ + + GOPAL のディレクトリ構成 — 4 つのトップレベル分岐、管轄区域と業種ごとに整理されたポリシー + +

``` gopal/ @@ -133,8 +149,6 @@ gopal/ ## 比較 -

GOPAL がカバーするフレームワーク — EU AI Act、NIST、FAA、EASA、RTCA など

- | | GOPAL | 汎用 OPA バンドル | ベンダー製ガバナンス SaaS | |---|---|---|---| | AI システムを明確に対象 | ✅ | ❌ | ✅ | @@ -152,7 +166,12 @@ gopal/ ## ポリシーの記述 -

GOPAL ポリシーの構造 — パッケージパス、import、メタデータ、default deny、allow ルール、レポート

+

+ + + GOPAL ポリシーの構造 — パッケージパス、import、メタデータ、default deny、allow ルール、レポート + +

すべてのポリシーは同じ構造に従います。 diff --git a/README.ko-KR.md b/README.ko-KR.md index 0c27065..ca8c246 100644 --- a/README.ko-KR.md +++ b/README.ko-KR.md @@ -1,4 +1,9 @@ -

GOPAL

+
+ + + GOPAL — The Rego policy library for AI compliance + +

English | @@ -8,10 +13,6 @@ हिन्दी

-

- AI 컴플라이언스를 위한 Rego 정책 라이브러리. -

-

94개 정책. 15개 이상의 규제 프레임워크. 5개 산업 수직 영역. 감사관이 읽을 수 있는 정책 코드화(policy-as-code).

@@ -34,13 +35,23 @@ 여러분의 AI 시스템 메타데이터, 모델 카드 또는 평가 결과에 대해 이러한 정책을 실행하면, CI, 감사 로그 또는 규제 당국 제출 자료에 그대로 적용할 수 있는 구조화된 기계 판독 가능 컴플라이언스 결과를 얻을 수 있습니다. -

GOPAL — 94개 정책, 15개 이상 프레임워크, 5개 수직 영역

+

+ + + GOPAL 커버리지: 94개 정책, 국제 표준 · 항공 · 산업 수직 · 공통 원칙의 4개 카테고리 + +

--- ## 빠른 시작 -

GOPAL 평가 동작 방식 — 입력 JSON, OPA 엔진, 정책, 판정 결과

+

+ + + GOPAL 평가 동작 방식 — 입력 JSON, Rego 정책, OPA 평가, 판정 결과 + +

### OPA CLI를 사용한 단독 실행 @@ -90,7 +101,12 @@ GOPAL은 세 가지 측면에서 다릅니다. ## 구성 내용 -

GOPAL 디렉터리 레이아웃 — 5개의 최상위 분기, 관할권 및 수직 영역별로 구성된 정책

+

+ + + GOPAL 디렉터리 레이아웃 — 4개의 최상위 분기, 관할권 및 수직 영역별로 구성된 정책 + +

``` gopal/ @@ -133,8 +149,6 @@ gopal/ ## 비교 -

GOPAL이 커버하는 프레임워크 — EU AI Act, NIST, FAA, EASA, RTCA 등

- | | GOPAL | 범용 OPA 번들 | 벤더 거버넌스 SaaS | |---|---|---|---| | AI 시스템을 특정해 대상화 | ✅ | ❌ | ✅ | @@ -152,7 +166,12 @@ gopal/ ## 정책 작성 -

GOPAL 정책의 구조 — 패키지 경로, 임포트, 메타데이터, 기본 거부, 허용 규칙, 리포트

+

+ + + GOPAL 정책의 구조 — 패키지 경로, 임포트, 메타데이터, 기본 거부, 허용 규칙, 리포트 + +

모든 정책은 동일한 형태를 따릅니다. diff --git a/README.md b/README.md index 569dccd..f79df12 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ -

GOPAL

+
+ + + GOPAL — The Rego policy library for AI compliance + +

English | @@ -8,10 +13,6 @@ हिन्दी

-

- The Rego policy library for AI compliance. -

-

94 policies. 15+ regulatory frameworks. 5 industry verticals. Policy-as-code your auditor can read.

@@ -34,13 +35,23 @@ Run them against your AI system's metadata, model cards, or evaluation results — and get back a structured, machine-readable compliance verdict you can drop into CI, an audit log, or a regulator submission. -

GOPAL — 94 policies, 15+ frameworks, 5 verticals

+

+ + + GOPAL coverage: 94 policies across international standards, aviation, industry verticals, and cross-cutting principles + +

--- ## Quick Start -

How GOPAL evaluation works — input JSON, OPA engine, policy, verdict

+

+ + + How GOPAL evaluation works — input JSON, Rego policy, OPA evaluation, verdict + +

### Standalone with the OPA CLI @@ -90,7 +101,12 @@ GOPAL is different on three axes: ## What's Inside -

GOPAL directory layout — 5 top-level branches, policies organized by jurisdiction and vertical

+

+ + + GOPAL directory layout — 4 top-level branches, policies organized by jurisdiction and vertical + +

``` gopal/ @@ -133,8 +149,6 @@ gopal/ ## Comparison -

Frameworks GOPAL covers — EU AI Act, NIST, FAA, EASA, RTCA and more

- | | GOPAL | Generic OPA bundle | Vendor governance SaaS | |---|---|---|---| | Targets AI systems specifically | ✅ | ❌ | ✅ | @@ -152,7 +166,12 @@ gopal/ ## Authoring Policies -

Anatomy of a GOPAL policy — package path, imports, metadata, default deny, allow rule, report

+

+ + + Anatomy of a GOPAL policy — package path, imports, metadata, default deny, allow rule, report + +

Every policy follows the same shape: diff --git a/README.zh-CN.md b/README.zh-CN.md index aa363a1..cf7997e 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,4 +1,9 @@ -

GOPAL

+
+ + + GOPAL — The Rego policy library for AI compliance + +

English | @@ -8,10 +13,6 @@ हिन्दी

-

- 面向 AI 合规的 Rego 策略库。 -

-

94 条策略。15+ 法规框架。5 个行业垂直领域。审计师能读懂的策略即代码。

@@ -34,13 +35,23 @@ 在您 AI 系统的元数据、模型卡片或评估结果上运行这些策略,即可获得结构化、机器可读的合规判定,可直接接入 CI、审计日志或监管报送。 -

GOPAL —— 94 条策略,15+ 框架,5 个垂直领域

+

+ + + GOPAL 覆盖范围:94 条策略,覆盖国际标准、航空、行业垂直与跨领域原则 + +

--- ## 快速开始 -

GOPAL 评估流程 —— 输入 JSON、OPA 引擎、策略、判定

+

+ + + GOPAL 评估流程 —— 输入 JSON、Rego 策略、OPA 评估、判定 + +

### 搭配 OPA CLI 独立使用 @@ -90,7 +101,12 @@ GOPAL 在三个维度上与众不同: ## 内容一览 -

GOPAL 目录结构 —— 5 个顶级分支,按司法管辖区与行业组织的策略

+

+ + + GOPAL 目录结构 —— 4 个顶级分支,按司法管辖区与行业组织的策略 + +

``` gopal/ @@ -133,8 +149,6 @@ gopal/ ## 对比 -

GOPAL 覆盖的框架 —— EU AI Act、NIST、FAA、EASA、RTCA 等

- | | GOPAL | 通用 OPA 规则包 | 厂商治理 SaaS | |---|---|---|---| | 专门面向 AI 系统 | ✅ | ❌ | ✅ | @@ -152,7 +166,12 @@ gopal/ ## 策略编写 -

GOPAL 策略的结构 —— 包路径、imports、元数据、默认拒绝、allow 规则、报告

+

+ + + GOPAL 策略的结构 —— 包路径、imports、元数据、默认拒绝、allow 规则、报告 + +

每条策略都遵循相同的结构: diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..bedd0d9 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,42 @@ +# Security Policy + +## Reporting a vulnerability + +If you find a security issue in GOPAL, please **do not file a public issue**. Email **security@principledevolution.ai** with: + +- A description of the issue +- Steps to reproduce +- The version (commit SHA or release tag) where you observed it +- Your assessment of severity (CVSS 3.1 if you have it) + +We aim to acknowledge within **5 business days**. We follow a coordinated-disclosure approach: we'll work with you on a fix and a disclosure timeline before any public announcement. + +## What's in scope + +- **CI / workflow vulnerabilities** in `.github/workflows/` (command injection, secret leakage, untrusted-input handling) +- **Supply-chain issues** in `pyproject.toml` (the Python distribution metadata that ships GOPAL as a package), or in the installer scripts in `CONTRIBUTING.md` / `README.md` +- **Helper-function bugs** in `helper_functions/*.rego` that could be exploited to bypass policy checks +- **Documentation issues** that would lead a reader to a less-secure configuration + +## What's NOT in scope + +- **Policy correctness disputes** — if you think a specific Rego rule is too strict, too lax, or misinterprets a regulation, please file a **public issue** rather than emailing security. That's a policy-design discussion, not a vulnerability, and is best done in the open with the community. +- **The regulations themselves** — GOPAL encodes published regulatory frameworks (EU AI Act, NIST AI RMF, etc.). Concerns about the underlying regulation belong with the regulator that issued it. +- **Generic OPA / Rego issues** — please report those to [open-policy-agent/opa](https://github.com/open-policy-agent/opa) or [StyraInc/regal](https://github.com/StyraInc/regal) directly. + +## Supported versions + +GOPAL ships under semver (see [COMPATIBILITY.md](COMPATIBILITY.md)). Security fixes are applied to: + +- The current `main` branch +- The current `vN/` directory under each framework + +Older versioned policy directories (`v1/` once `v2/` ships) are treated as frozen reference artefacts — they will not receive security updates. If your deployment pins to an older policy version, plan to migrate. + +## Public attribution + +We are happy to credit reporters in the changelog and release notes unless you ask us not to. + +--- + +This policy will evolve as the project grows. Last reviewed: 2026-05. diff --git a/diagrams/STYLE.md b/diagrams/STYLE.md new file mode 100644 index 0000000..0bc4144 --- /dev/null +++ b/diagrams/STYLE.md @@ -0,0 +1,99 @@ +# GOPAL diagram style + +A short, opinionated reference so future diagrams (yours, mine, or a contributor's) stay visually coherent with the existing set. If you can read [diagram5_evaluation_flow_light.svg](diagram5_evaluation_flow_light.svg) and the matching `_dark.svg`, you have already seen the whole system applied. + +GOPAL and its sister project [AICertify](https://github.com/Principled-Evolution/aicertify) share this design system on purpose — readers seeing both repos should recognise a family resemblance. + +## The principle + +Two colors with intent, flat fills, no animation, no shadows. The polish is in restraint and consistency, not effects. + +## Palette + +| Token | Light | Dark | Used for | +|---|---|---|---| +| **Indigo (primary)** | `#4f46e5` | `#6366f1` | Process, structure, the "happy path" | +| **Indigo (light fill)** | `#eef2ff` | `#312e81` | Card backgrounds for indigo elements | +| **Indigo (text on fill)** | `#4338ca` | `#c7d2fe` | Text inside indigo chips/badges | +| **Amber (accent)** | `#d97706` | `#fbbf24` | The **deliverable** — verdict, report, the thing the reader walks away with | +| **Amber (light fill)** | `#fffbeb` / `#fef3c7` | `#2a1f06` / `#533404` | Card / chip backgrounds for amber elements | +| **Amber (text on fill)** | `#92400e` / `#b45309` | `#fcd34d` / `#fde68a` | Text inside amber chips | +| **Foreground (text)** | `#0f172a` | `#f0f6fc` | Primary body / heading text | +| **Foreground (muted)** | `#64748b` | `#8b949e` | Secondary captions, labels | +| **Border** | `#e2e8f0` | `#30363d` | Card outlines, dividers | +| **Card surface** | `#ffffff` | `#161b22` | Card backgrounds | +| **Arrow / line** | `#94a3b8` | `#6e7681` | Connectors | + +**Amber is precious.** Reserve it for the deliverable in a flow (the verdict, the report) and never use it decoratively. If everything is highlighted, nothing is highlighted. + +## Typography + +- Single stack, declared on every ``: `font-family="system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"`. No webfont hosting, no licensing, picks up the reader's OS font. +- **Monospace** (for Rego code, package paths, directory names): `font-family="ui-monospace, SFMono-Regular, Menlo, monospace"`. +- **Headings inside cards**: 13–15px, `font-weight="500"`. +- **Body / captions**: 10–12px, `font-weight="400"`. +- **Stat numerals** (e.g. "94"): 36px, `font-weight="500"`, amber. +- Wordmark on the hero banner / OG card uses `letter-spacing="-0.025em"` for tightness at large sizes. + +**On multi-coloured text** (e.g. Rego syntax highlighting in `diagram3_policy_anatomy`): use `` inside `` and set `xml:space="preserve"` on the containing element — without it, Inkscape and some browsers normalise whitespace between tspans and your colored keywords run together. + +## Shape language + +- **Cards / chips**: rounded rectangles. Corner radius `rx="10"` for cards, `rx="12"` (or larger) for chip pills. +- **Card stroke**: `1px` border in the border token, no shadows, no gradients. +- **Arrows**: `1.5px` line in the muted line color, with the marker defined per-file in ``. Don't reuse `id="al"` etc. across files in case both are inlined. +- **Icons inside cards**: `1.5px` stroke in the indigo (or dark variant) color, `stroke-linecap="round"`, `stroke-linejoin="round"`. Compact (~24×24 unit) line icons, no fills unless intentional. + +## Light/dark pattern + +Diagrams ship as **paired files** with matching `_light.svg` and `_dark.svg`. README markup uses ``: + +```html + + + <descriptive alt text> +
+``` + +That gives GitHub-light readers the light variant and GitHub-dark readers the dark variant — same on mobile, on PR previews, and anywhere else `` is honored. + +- Light variants use white card surfaces, slate text. +- Dark variants use `#161b22` cards (GitHub's `--color-canvas-subtle`) and `#30363d` borders so cards sit into the page rather than floating on top of it. +- Don't bake in a background `` filling the viewBox unless the asset is meant to be self-contained (e.g. OG cards). Otherwise let GitHub's page color show through. + +## Files and naming + +``` +diagrams/ +├── STYLE.md (this file) +├── hero_banner_{light,dark}.svg top-of-README banner +├── logo_{light,dark}.svg standalone square mark +├── og_card_{light,dark}.svg 1200×630 social-preview card +├── og_card.png rasterized light variant, for GitHub Settings → Social preview +├── diagram1_hero_numbers_{light,dark}.svg 94 / 15+ / 5 stats + 4 category cards +├── diagram2_directory_tree_{light,dark}.svg 4 top-level directories with policy counts +├── diagram3_policy_anatomy_{light,dark}.svg Rego policy mockup with callouts +└── diagram5_evaluation_flow_{light,dark}.svg input → policy → OPA → verdict +``` + +A previous `diagram4_framework_grid` was retired — the markdown comparison table in the README is the single source of truth. + +## Adding a new diagram + +1. Sketch the content first in markdown (what does the reader need to understand?). Cut anything that is also said in nearby text. +2. Pick a layout that mirrors an existing diagram if you can — most additions are variations of "flow", "accordion", "stats + cards", or "mockup + callouts". +3. Hand-author the SVG. Use the existing files as templates; copy a card definition, swap the content. +4. Validate XML: `python3 -c "import xml.etree.ElementTree as ET; ET.parse('diagrams/_light.svg')"`. Repeat for the dark variant. +5. Embed with the `` snippet above in every README that should reference it (en + 4 translated). +6. **No automation, no matplotlib, no Python generator.** The old `generate_diagrams.py` was retired because hand-authored SVGs are easier to read, edit, and review than rendered raster output. Keep them hand-authored. + +## Rasterizing (only when needed) + +The only raster output we keep in the repo is `og_card.png` — GitHub's Social Preview upload requires PNG/JPG. To regenerate: + +```bash +inkscape --export-type=png --export-width=1200 --export-height=630 \ + --export-filename=diagrams/og_card.png diagrams/og_card_light.svg +``` + +GitHub social preview is uploaded manually at: **Settings → General → Social preview → Edit → Upload an image**. The repo's checked-in `og_card.png` is the source artifact. diff --git a/diagrams/diagram1_hero_numbers.png b/diagrams/diagram1_hero_numbers.png deleted file mode 100644 index fc52238..0000000 Binary files a/diagrams/diagram1_hero_numbers.png and /dev/null differ diff --git a/diagrams/diagram1_hero_numbers_dark.svg b/diagrams/diagram1_hero_numbers_dark.svg new file mode 100644 index 0000000..fd9d030 --- /dev/null +++ b/diagrams/diagram1_hero_numbers_dark.svg @@ -0,0 +1,70 @@ + + +GOPAL coverage +94 production Rego policies across 15+ frameworks and 5 industries. + +94 +Rego policies +15+ +frameworks +5 +industries + + + + + + + + + +International standards + +EU AI Act 2024/1689 (29) +NIST AI RMF + AI 600-1 +India Digital Policy +Brazil AI Governance Bill + + + + + + + + +Aviation (26 policies) + +ICAO Doc 10019 +FAA Part 107, Remote ID +EASA SORA, Reg 2019/947 +RTCA DO-365/366, ASTM F3442 + + + + + + + + +Industry verticals (17) + +Education (12) — FERPA, COPPA +Healthcare — patient safety +Banking — model risk, fair lending +Automotive — vehicle safety + + + + + + + + +Cross-cutting + ops (13) + +Fairness, transparency, content safety +Explainability, risk management +Security, accountability +AIOps, cost, corporate InfoSec + + diff --git a/diagrams/diagram1_hero_numbers_light.svg b/diagrams/diagram1_hero_numbers_light.svg new file mode 100644 index 0000000..2fb70fc --- /dev/null +++ b/diagrams/diagram1_hero_numbers_light.svg @@ -0,0 +1,70 @@ + + +GOPAL coverage +94 production Rego policies across 15+ frameworks and 5 industries. + +94 +Rego policies +15+ +frameworks +5 +industries + + + + + + + + + +International standards + +EU AI Act 2024/1689 (29) +NIST AI RMF + AI 600-1 +India Digital Policy +Brazil AI Governance Bill + + + + + + + + +Aviation (26 policies) + +ICAO Doc 10019 +FAA Part 107, Remote ID +EASA SORA, Reg 2019/947 +RTCA DO-365/366, ASTM F3442 + + + + + + + + +Industry verticals (17) + +Education (12) — FERPA, COPPA +Healthcare — patient safety +Banking — model risk, fair lending +Automotive — vehicle safety + + + + + + + + +Cross-cutting + ops (13) + +Fairness, transparency, content safety +Explainability, risk management +Security, accountability +AIOps, cost, corporate InfoSec + + diff --git a/diagrams/diagram2_directory_tree.png b/diagrams/diagram2_directory_tree.png deleted file mode 100644 index bbd6e7e..0000000 Binary files a/diagrams/diagram2_directory_tree.png and /dev/null differ diff --git a/diagrams/diagram2_directory_tree_dark.svg b/diagrams/diagram2_directory_tree_dark.svg new file mode 100644 index 0000000..53cd38c --- /dev/null +++ b/diagrams/diagram2_directory_tree_dark.svg @@ -0,0 +1,77 @@ + + +GOPAL repository layout +Four top-level directories — international, industry-specific, global, operational — with policy counts and versioned children. + + + + + + + +international/ +45 policies · 8 frameworks + +eu_ai_act/v1/ (29) +nist/v1/ (5) +india/v1/ (1) +brazil/v1/ (1) +icao/v1/ (1) +faa/v1/ (2) +easa/v1/ (2) +standards/v1/ (4) + + + + + + + + + +industry_specific/ +34 policies · 5 verticals + +aviation/v1/ (17) +education/v1/ (12) +healthcare/v1/ (2) +bfs/v1/ (2) +automotive/v1/ (1) + + + + + + + + + +global/v1/ +9 cross-cutting policies + +fairness.rego +transparency.rego +content_safety.rego +risk_management.rego +explainability.rego +security.rego · accountability.rego + + + + + + + + + +operational/ +4 policies · 3 categories + +aiops/v1/ (1) +cost/v1/ (1) +corporate/v1/ (2) + + + +Every framework is pinned at v1/. When a regulation amends, v2/ ships alongside. + diff --git a/diagrams/diagram2_directory_tree_light.svg b/diagrams/diagram2_directory_tree_light.svg new file mode 100644 index 0000000..213afd8 --- /dev/null +++ b/diagrams/diagram2_directory_tree_light.svg @@ -0,0 +1,77 @@ + + +GOPAL repository layout +Four top-level directories — international, industry-specific, global, operational — with policy counts and versioned children. + + + + + + + +international/ +45 policies · 8 frameworks + +eu_ai_act/v1/ (29) +nist/v1/ (5) +india/v1/ (1) +brazil/v1/ (1) +icao/v1/ (1) +faa/v1/ (2) +easa/v1/ (2) +standards/v1/ (4) + + + + + + + + + +industry_specific/ +34 policies · 5 verticals + +aviation/v1/ (17) +education/v1/ (12) +healthcare/v1/ (2) +bfs/v1/ (2) +automotive/v1/ (1) + + + + + + + + + +global/v1/ +9 cross-cutting policies + +fairness.rego +transparency.rego +content_safety.rego +risk_management.rego +explainability.rego +security.rego · accountability.rego + + + + + + + + + +operational/ +4 policies · 3 categories + +aiops/v1/ (1) +cost/v1/ (1) +corporate/v1/ (2) + + + +Every framework is pinned at v1/. When a regulation amends, v2/ ships alongside. + diff --git a/diagrams/diagram3_policy_anatomy.png b/diagrams/diagram3_policy_anatomy.png deleted file mode 100644 index e191a78..0000000 Binary files a/diagrams/diagram3_policy_anatomy.png and /dev/null differ diff --git a/diagrams/diagram3_policy_anatomy_dark.svg b/diagrams/diagram3_policy_anatomy_dark.svg new file mode 100644 index 0000000..da1aeae --- /dev/null +++ b/diagrams/diagram3_policy_anatomy_dark.svg @@ -0,0 +1,69 @@ + + +Anatomy of a GOPAL policy +Stylized Rego policy file showing package path, imports, metadata, default deny, allow rule, and report composition. + + + + + + + +transparency.rego + + +package international.eu_ai_act.v1 + .transparency + +import data.helper_functions + .reporting + +# METADATA +# title: Transparency for GPAI +# description: Article 53 ... + +default allow := false + +allow if { + input.system.docs_published + input.system.training_summary +} + +report := reporting + .compose_report( + "eu_ai_act.transparency", + allow, + [...] +) + + + + +Package path +Versioned namespace, mirrors directory + + + +Imports +Shared helpers from helper_functions/ + + + +METADATA +Audit-readable; consumed by tooling + + + +Default deny +Safe by default if rule never fires + + + +Allow condition +The actual compliance check + + + +Report +Standardized output the auditor reads + diff --git a/diagrams/diagram3_policy_anatomy_light.svg b/diagrams/diagram3_policy_anatomy_light.svg new file mode 100644 index 0000000..fa4469e --- /dev/null +++ b/diagrams/diagram3_policy_anatomy_light.svg @@ -0,0 +1,69 @@ + + +Anatomy of a GOPAL policy +Stylized Rego policy file showing package path, imports, metadata, default deny, allow rule, and report composition. + + + + + + + +transparency.rego + + +package international.eu_ai_act.v1 + .transparency + +import data.helper_functions + .reporting + +# METADATA +# title: Transparency for GPAI +# description: Article 53 ... + +default allow := false + +allow if { + input.system.docs_published + input.system.training_summary +} + +report := reporting + .compose_report( + "eu_ai_act.transparency", + allow, + [...] +) + + + + +Package path +Versioned namespace, mirrors directory + + + +Imports +Shared helpers from helper_functions/ + + + +METADATA +Audit-readable; consumed by tooling + + + +Default deny +Safe by default if rule never fires + + + +Allow condition +The actual compliance check + + + +Report +Standardized output the auditor reads + diff --git a/diagrams/diagram4_framework_grid.png b/diagrams/diagram4_framework_grid.png deleted file mode 100644 index 45daf8c..0000000 Binary files a/diagrams/diagram4_framework_grid.png and /dev/null differ diff --git a/diagrams/diagram5_evaluation_flow.png b/diagrams/diagram5_evaluation_flow.png deleted file mode 100644 index 146be00..0000000 Binary files a/diagrams/diagram5_evaluation_flow.png and /dev/null differ diff --git a/diagrams/diagram5_evaluation_flow_dark.svg b/diagrams/diagram5_evaluation_flow_dark.svg new file mode 100644 index 0000000..9918123 --- /dev/null +++ b/diagrams/diagram5_evaluation_flow_dark.svg @@ -0,0 +1,61 @@ + + +How GOPAL evaluation works +Four-step flow from input data and Rego policy through the OPA engine to a verdict. + + + + + + + +01 + + + + +Input JSON +AI system data + + + + + + + +02 + + + + +Rego policy +gopal library + + + + + + + +03 + + + + +OPA evaluation +Engine runs the rule + + + + + + + +04 + + + +Verdict +Allow · Deny · Reason + + diff --git a/diagrams/diagram5_evaluation_flow_light.svg b/diagrams/diagram5_evaluation_flow_light.svg new file mode 100644 index 0000000..c1fbdc8 --- /dev/null +++ b/diagrams/diagram5_evaluation_flow_light.svg @@ -0,0 +1,61 @@ + + +How GOPAL evaluation works +Four-step flow from input data and Rego policy through the OPA engine to a verdict. + + + + + + + +01 + + + + +Input JSON +AI system data + + + + + + + +02 + + + + +Rego policy +gopal library + + + + + + + +03 + + + + +OPA evaluation +Engine runs the rule + + + + + + + +04 + + + +Verdict +Allow · Deny · Reason + + diff --git a/diagrams/generate_diagrams.py b/diagrams/generate_diagrams.py deleted file mode 100644 index ef7f6ba..0000000 --- a/diagrams/generate_diagrams.py +++ /dev/null @@ -1,599 +0,0 @@ -"""Generate marketing diagrams for the GOPAL README. - -Run from repo root: - python diagrams/generate_diagrams.py - -Outputs 5 PNGs (1600x900) into diagrams/. -""" - -from __future__ import annotations - -import os -from pathlib import Path - -import matplotlib.pyplot as plt -import matplotlib.patches as mpatches -from matplotlib.patches import FancyBboxPatch, FancyArrowPatch, Rectangle -from matplotlib.lines import Line2D - -# --- Palette ---------------------------------------------------------------- -PURPLE = "#7D4698" -BLUE = "#1971c2" -GREEN = "#2f9e44" -ORANGE = "#e8590c" -TEXT = "#495057" -LIGHT_BG = "#dee2e6" -WHITE = "#ffffff" -CODE_BG = "#f1f3f5" -CODE_BORDER = "#ced4da" - -# Figure dimensions: 1600x900 at dpi=100 -> figsize = (16, 9) -FIGSIZE = (16, 9) -DPI = 100 - -OUT_DIR = Path(__file__).parent - - -# --- Helpers ---------------------------------------------------------------- -def new_canvas(): - """Create a 16:9 white canvas with a 0-1600 x 0-900 coord system.""" - fig, ax = plt.subplots(figsize=FIGSIZE, dpi=DPI) - ax.set_xlim(0, 1600) - ax.set_ylim(0, 900) - ax.set_aspect("equal") - ax.set_facecolor(WHITE) - fig.patch.set_facecolor(WHITE) - ax.axis("off") - return fig, ax - - -def save(fig, name: str): - out = OUT_DIR / name - fig.savefig( - out, - dpi=DPI, - bbox_inches="tight", - facecolor=WHITE, - edgecolor="none", - pad_inches=0.15, - ) - plt.close(fig) - size_kb = out.stat().st_size / 1024 - print(f" -> {name} ({size_kb:,.1f} KB)") - return out - - -def draw_title(ax, text: str, y: float = 830, fontsize: int = 32, color: str = TEXT): - ax.text( - 800, y, text, - ha="center", va="center", - fontsize=fontsize, fontweight="bold", color=color, - family="DejaVu Sans", - ) - - -def draw_subtitle(ax, text: str, y: float = 790, fontsize: int = 18, color: str = TEXT): - ax.text( - 800, y, text, - ha="center", va="center", - fontsize=fontsize, color=color, - family="DejaVu Sans", - ) - - -def rounded_box(ax, x, y, w, h, *, facecolor, edgecolor=None, lw=1.5, radius=0.025, zorder=2): - """Draw a rounded rectangle. (x, y) is bottom-left.""" - box = FancyBboxPatch( - (x, y), w, h, - boxstyle=f"round,pad=0,rounding_size={radius * min(w, h) * 8}", - facecolor=facecolor, - edgecolor=edgecolor if edgecolor else facecolor, - linewidth=lw, - zorder=zorder, - ) - ax.add_patch(box) - return box - - -def card(ax, x, y, w, h, *, fill=PURPLE, edge=None, radius=14): - """Simpler rounded card with absolute corner radius.""" - box = FancyBboxPatch( - (x, y), w, h, - boxstyle=f"round,pad=0,rounding_size={radius}", - facecolor=fill, - edgecolor=edge if edge else fill, - linewidth=1.5, - zorder=2, - ) - ax.add_patch(box) - return box - - -def text(ax, x, y, s, *, size=18, color=TEXT, weight="normal", ha="center", va="center", family="DejaVu Sans"): - ax.text(x, y, s, fontsize=size, color=color, fontweight=weight, ha=ha, va=va, family=family, zorder=5) - - -def arrow(ax, x1, y1, x2, y2, *, color=TEXT, lw=2.0, style="-|>", mutation=20): - a = FancyArrowPatch( - (x1, y1), (x2, y2), - arrowstyle=style, - mutation_scale=mutation, - linewidth=lw, - color=color, - zorder=4, - ) - ax.add_patch(a) - - -# === Diagram 1: Hero Numbers ================================================ -def diagram1_hero_numbers(): - fig, ax = new_canvas() - - draw_title(ax, "GOPAL — the Rego policy library for AI compliance", - y=830, fontsize=30) - draw_subtitle(ax, "Policy-as-code your auditor can read", - y=780, fontsize=20, color=PURPLE) - - # Three big number cards - cards = [ - ("94", "Production", "Policies"), - ("15+", "Regulatory", "Frameworks"), - ("5", "Industry", "Verticals"), - ] - card_w, card_h = 460, 400 - gap = 40 - total_w = 3 * card_w + 2 * gap - start_x = (1600 - total_w) / 2 - y0 = 300 - - for i, (num, label1, label2) in enumerate(cards): - x = start_x + i * (card_w + gap) - # Outer card - card(ax, x, y0, card_w, card_h, fill=PURPLE, radius=24) - # Big number - text(ax, x + card_w / 2, y0 + card_h / 2 + 50, num, - size=140, weight="bold", color=WHITE) - # Divider - ax.plot([x + 80, x + card_w - 80], [y0 + 110, y0 + 110], - color="#a577c0", lw=1.5, zorder=4) - # Label (two lines) - text(ax, x + card_w / 2, y0 + 75, label1, - size=22, weight="bold", color=WHITE) - text(ax, x + card_w / 2, y0 + 40, label2, - size=22, weight="bold", color=WHITE) - - # Verticals strip - text(ax, 800, 240, - "Aviation · Education · Healthcare · BFS · Automotive", - size=22, weight="bold", color=BLUE) - - # Footer pill - footer = "Apache 2.0 · OPA-native · Versioned (v1, v2, …)" - pill_w, pill_h = 880, 64 - px = (1600 - pill_w) / 2 - py = 120 - card(ax, px, py, pill_w, pill_h, fill=LIGHT_BG, radius=32) - text(ax, 800, py + pill_h / 2, footer, size=20, weight="bold", color=TEXT) - - save(fig, "diagram1_hero_numbers.png") - - -# === Diagram 2: Directory Tree ============================================== -def diagram2_directory_tree(): - fig, ax = new_canvas() - - draw_title(ax, "What's inside", y=850, fontsize=34) - draw_subtitle(ax, "94 production policies, organized by jurisdiction and vertical", - y=805, fontsize=18) - - # Root box - root_x, root_y, root_w, root_h = 700, 720, 200, 56 - card(ax, root_x, root_y, root_w, root_h, fill=TEXT, radius=10) - text(ax, root_x + root_w / 2, root_y + root_h / 2, "gopal/", - size=22, weight="bold", color=WHITE) - - # 5 branch group headers - branches = [ - # (label, color, x_center, [leaves]) - ("international/", PURPLE, 175, - [("eu_ai_act/v1", "29"), - ("nist/v1", "5"), - ("india/v1", "1"), - ("brazil/v1", "1"), - ("icao/faa/easa", "5"), - ("standards/v1", "4")]), - ("industry/", BLUE, 500, - [("aviation/v1", "17"), - ("education/v1", "12"), - ("healthcare/v1", "2"), - ("bfs/v1", "2"), - ("automotive/v1", "1")]), - ("global/v1", GREEN, 820, - [("accountability", ""), - ("fairness", ""), - ("transparency", ""), - ("explainability", ""), - ("content_safety", "9")]), - ("operational/", ORANGE, 1140, - [("aiops/v1", "1"), - ("cost/v1", "1"), - ("corporate/v1", "2")]), - ("helpers/", TEXT, 1420, - [("reporting.rego", ""), - ("validation.rego", "")]), - ] - - # Branch headers (under root) - branch_y = 605 - branch_h = 52 - branch_w = 280 - - for label, color, cx, leaves in branches: - # Branch header card - bx = cx - branch_w / 2 - card(ax, bx, branch_y, branch_w, branch_h, fill=color, radius=10) - text(ax, cx, branch_y + branch_h / 2, label, - size=16, weight="bold", color=WHITE) - - # Line from root to branch header - root_cx = root_x + root_w / 2 - root_bottom = root_y - # Trunk drops to a horizontal bus - bus_y = 690 - ax.plot([root_cx, root_cx], [root_bottom, bus_y], color=TEXT, lw=1.5, zorder=1) - ax.plot([root_cx, cx], [bus_y, bus_y], color=TEXT, lw=1.5, zorder=1) - ax.plot([cx, cx], [bus_y, branch_y + branch_h], color=color, lw=2.0, zorder=1) - - # Leaves - leaf_w = 280 - leaf_h = 44 - leaf_gap = 12 - leaf_x = cx - leaf_w / 2 - for i, (lbl, count) in enumerate(leaves): - ly = branch_y - 30 - i * (leaf_h + leaf_gap) - card(ax, leaf_x, ly, leaf_w, leaf_h, fill=WHITE, edge=color, radius=8) - # Left coloured stripe - stripe = Rectangle((leaf_x, ly), 6, leaf_h, facecolor=color, edgecolor=color, zorder=3) - ax.add_patch(stripe) - - if count: - # label left, count right (in colored pill) - # Use smaller font and shift label slightly left to avoid pill overlap - text(ax, leaf_x + 18, ly + leaf_h / 2, lbl, size=13, color=TEXT, - ha="left", weight="bold") - # count pill - pill_w = 42 - px = leaf_x + leaf_w - pill_w - 8 - py = ly + (leaf_h - 26) / 2 - card(ax, px, py, pill_w, 26, fill=color, radius=8) - text(ax, px + pill_w / 2, py + 13, count, size=14, color=WHITE, weight="bold") - else: - text(ax, leaf_x + 18, ly + leaf_h / 2, lbl, size=13, color=TEXT, - ha="left") - - # connecting tick from branch - ax.plot([cx, cx], [branch_y, ly + leaf_h / 2], color=color, lw=1.2, - alpha=0.35, zorder=0) - - # Legend at bottom - legend_y = 60 - legend_items = [ - ("International", PURPLE), - ("Industry", BLUE), - ("Global", GREEN), - ("Operational", ORANGE), - ("Helpers", TEXT), - ] - total = len(legend_items) - spacing = 240 - start = 800 - (total - 1) * spacing / 2 - for i, (lbl, col) in enumerate(legend_items): - x = start + i * spacing - # swatch - sw = Rectangle((x - 80, legend_y), 18, 18, facecolor=col, edgecolor=col, zorder=3) - ax.add_patch(sw) - text(ax, x - 55, legend_y + 9, lbl, size=15, color=TEXT, ha="left", weight="bold") - - save(fig, "diagram2_directory_tree.png") - - -# === Diagram 3: Policy Anatomy ============================================== -def diagram3_policy_anatomy(): - fig, ax = new_canvas() - - draw_title(ax, "Anatomy of a GOPAL policy", y=840, fontsize=34) - draw_subtitle(ax, "Every rule is a small, readable Rego file", y=795, fontsize=18) - - # Code block background - code_x, code_y, code_w, code_h = 70, 130, 820, 600 - rounded_box(ax, code_x, code_y, code_w, code_h, facecolor=CODE_BG, - edgecolor=CODE_BORDER, lw=1.5, radius=0.04) - - # Window dots (terminal/editor chrome) - for i, c in enumerate(["#ff5f57", "#febc2e", "#28c840"]): - circ = mpatches.Circle((code_x + 26 + i * 22, code_y + code_h - 22), 8, - facecolor=c, edgecolor=c, zorder=4) - ax.add_patch(circ) - text(ax, code_x + code_w / 2, code_y + code_h - 22, - "transparency.rego", size=14, color=TEXT, family="DejaVu Sans Mono") - - # Header bar separator - ax.plot([code_x, code_x + code_w], - [code_y + code_h - 44, code_y + code_h - 44], - color=CODE_BORDER, lw=1.2) - - # Code lines with anchor points (x_anchor at right side of code box for callouts) - # Each: (text, color, y, has_callout) - code_lines = [ - ("package international.eu_ai_act.v1.transparency", PURPLE, 640, True), - ("", TEXT, 615, False), - ("import data.helper_functions.reporting", BLUE, 590, True), - ("", TEXT, 565, False), - ("# METADATA", "#868e96", 540, True), - ("# title: GPAI transparency obligations", "#868e96", 515, False), - ("# source: https://eur-lex.europa.eu/...", "#868e96", 490, False), - ("", TEXT, 465, False), - ("default allow := false", ORANGE, 440, True), - ("", TEXT, 415, False), - ("allow if {", GREEN, 390, True), - (" input.system.documentation_published == true", TEXT, 365, False), - ("}", GREEN, 340, False), - ("", TEXT, 315, False), - ("report := reporting.compose_report(...)", BLUE, 290, True), - ] - - code_left = code_x + 30 - for line, color, y, _ in code_lines: - text(ax, code_left, y, line, - size=15, color=color, ha="left", - family="DejaVu Sans Mono", - weight="bold" if color in (PURPLE, ORANGE, GREEN) and line else "normal") - - # Callouts on the right side - callouts = [ - (640, "Mirrors directory path", PURPLE), - (590, "Shared utilities", BLUE), - (540, "Tooling + auditor metadata", "#495057"), - (440, "Safe default — fail closed", ORANGE), - (390, "The rule itself", GREEN), - (290, "Uniform report shape", BLUE), - ] - - callout_x = 980 # left edge of callout column - callout_w = 540 - callout_h = 56 - - for y, msg, col in callouts: - cy = y - callout_h / 2 - # Callout pill - card(ax, callout_x, cy, callout_w, callout_h, fill=WHITE, edge=col, radius=14) - # Left stripe - stripe = Rectangle((callout_x, cy), 6, callout_h, facecolor=col, edgecolor=col, zorder=3) - ax.add_patch(stripe) - text(ax, callout_x + 22, cy + callout_h / 2, msg, - size=17, weight="bold", color=col, ha="left") - - # Arrow from code line to callout - arrow(ax, code_x + code_w - 10, y, callout_x - 4, y, - color=col, lw=1.8, mutation=14) - - # Footer caption - text(ax, 800, 80, - "package path = directory path · default deny · compose_report() everywhere", - size=18, weight="bold", color=TEXT) - - save(fig, "diagram3_policy_anatomy.png") - - -# === Diagram 4: Framework Grid ============================================== -def diagram4_framework_grid(): - fig, ax = new_canvas() - - draw_title(ax, "Frameworks covered", y=850, fontsize=34) - draw_subtitle(ax, "15+ named regulations across 5 verticals — every rule open and readable", - y=807, fontsize=17) - - rows = [ - ("INTERNATIONAL", [("EU AI Act", "29"), ("NIST AI RMF", "5"), - ("India DPDP", "1"), ("Brazil AI", "1")]), - ("AVIATION SAFETY", [("RTCA DO-365", "1"), ("RTCA DO-366", "1"), - ("FAA Part 107", "1"), ("EASA SORA", "1")]), - ("INDUSTRY", [("Aviation", "17"), ("Education", "12"), - ("Healthcare", "2"), ("BFS", "2")]), - ("CROSS-CUTTING", [("Global", "9"), ("AIOps", "1"), - ("Corporate", "2"), ("Automotive", "1")]), - ] - - # Grid layout - n_cols = 4 - cell_w = 290 - cell_h = 115 - gap_x = 24 - gap_y = 28 - - total_grid_w = n_cols * cell_w + (n_cols - 1) * gap_x - # Reserve room on the left for row labels - label_col_w = 175 - grid_left = (1600 - total_grid_w - label_col_w) / 2 + label_col_w - start_x = grid_left - # Top of first row - top_y = 640 - - for r, (row_label, cells) in enumerate(rows): - y = top_y - r * (cell_h + gap_y) - - # Row label on the left - text(ax, start_x - 28, y + cell_h / 2, row_label, - size=14, weight="bold", color=TEXT, ha="right", family="DejaVu Sans") - - for c, (name, count) in enumerate(cells): - x = start_x + c * (cell_w + gap_x) - card(ax, x, y, cell_w, cell_h, fill=PURPLE, radius=14) - # Framework name - text(ax, x + cell_w / 2, y + cell_h / 2 + 18, - name, size=21, weight="bold", color=WHITE) - # Divider - ax.plot([x + 60, x + cell_w - 60], [y + cell_h / 2 - 3, y + cell_h / 2 - 3], - color="#a577c0", lw=1.2, zorder=4) - # Count line - text(ax, x + cell_w / 2, y + cell_h / 2 - 24, - f"{count} polic{'y' if count == '1' else 'ies'}", - size=15, color="#e9d8f4") - - # Footer - text(ax, 800, 90, - "All policies in this library are Apache-2.0 and live under /v1/ paths", - size=18, weight="bold", color=TEXT) - - save(fig, "diagram4_framework_grid.png") - - -# === Diagram 5: Evaluation Flow ============================================= -def diagram5_evaluation_flow(): - fig, ax = new_canvas() - - draw_title(ax, "How evaluation works", y=840, fontsize=34) - draw_subtitle(ax, "From your AI system metadata to a structured compliance verdict", - y=795, fontsize=18) - - # 4 stages, horizontal flow - stage_w = 320 - stage_h = 420 - gap = 50 - total_w = 4 * stage_w + 3 * gap - start_x = (1600 - total_w) / 2 - y0 = 230 - - stages = [ - { - "title": "Your input.json", - "color": BLUE, - "lines": [ - "{", - ' "system": {', - ' "name":', - ' "GPT-Risk-Bot",', - ' "docs":', - ' "published",', - ' "training":', - ' "summarized"', - " }", - "}", - ], - "tag": "INPUT", - }, - { - "title": "OPA Engine", - "color": TEXT, - "lines": [ - "$ opa eval \\", - " -d international/ \\", - " --input sys.json \\", - ' "data.intl.', - ' eu_ai_act.v1.', - ' transparency', - ' .allow"', - ], - "tag": "ENGINE", - }, - { - "title": "GOPAL Policy", - "color": PURPLE, - "lines": [ - "package", - " international", - " .eu_ai_act.v1", - " .transparency", - "", - "default allow", - " := false", - "", - "allow if {", - ' input.docs ==', - ' "published"', - "}", - ], - "tag": "POLICY", - }, - { - "title": "Verdict", - "color": GREEN, - "lines": [ - "{", - ' "allow": false,', - ' "report": {', - ' "rule":', - ' "transparency",', - ' "metrics": [', - ' { "passed":', - ' false }', - " ]", - " }", - "}", - ], - "tag": "OUTPUT", - }, - ] - - for i, s in enumerate(stages): - x = start_x + i * (stage_w + gap) - col = s["color"] - - # Card body (white with coloured border) - card(ax, x, y0, stage_w, stage_h, fill=WHITE, edge=col, radius=18) - # Coloured header band - header_h = 60 - card(ax, x, y0 + stage_h - header_h, stage_w, header_h, fill=col, radius=18) - # Cover bottom of header so it looks like only the top is rounded - rect = Rectangle((x, y0 + stage_h - header_h), - stage_w, header_h / 2, facecolor=col, edgecolor=col, zorder=3) - ax.add_patch(rect) - - # Tag (small uppercase, top of header) - text(ax, x + stage_w / 2, y0 + stage_h - 18, - s["tag"], size=12, color="#ffffffcc", weight="bold") - # Title - text(ax, x + stage_w / 2, y0 + stage_h - 42, - s["title"], size=20, color=WHITE, weight="bold") - - # Code/text body - line_y0 = y0 + stage_h - header_h - 36 - line_step = 24 - for j, line in enumerate(s["lines"]): - text(ax, x + 22, line_y0 - j * line_step, line, - size=12.5, color=TEXT, ha="left", - family="DejaVu Sans Mono") - - # Arrow to next stage - if i < len(stages) - 1: - ax1 = x + stage_w + 6 - ax2 = x + stage_w + gap - 6 - ay = y0 + stage_h / 2 - arrow(ax, ax1, ay, ax2, ay, color=TEXT, lw=3.0, mutation=26) - - # Sub-caption - pill_w, pill_h = 1040, 70 - px = (1600 - pill_w) / 2 - py = 100 - card(ax, px, py, pill_w, pill_h, fill=LIGHT_BG, radius=35) - text(ax, 800, py + pill_h / 2, - "Pure functions of input and data. No I/O. Reproducible.", - size=22, weight="bold", color=TEXT) - - save(fig, "diagram5_evaluation_flow.png") - - -# === Main =================================================================== -def main(): - print(f"Generating diagrams into: {OUT_DIR}") - OUT_DIR.mkdir(parents=True, exist_ok=True) - diagram1_hero_numbers() - diagram2_directory_tree() - diagram3_policy_anatomy() - diagram4_framework_grid() - diagram5_evaluation_flow() - print("Done.") - - -if __name__ == "__main__": - main() diff --git a/diagrams/hero_banner_dark.svg b/diagrams/hero_banner_dark.svg new file mode 100644 index 0000000..ecd5cad --- /dev/null +++ b/diagrams/hero_banner_dark.svg @@ -0,0 +1,26 @@ + + +GOPAL +GOPAL hero banner with logo, wordmark, tagline, and framework badges. + + + + + +GOPAL +The Rego policy library for AI compliance +94 policies · 15+ frameworks · Apache 2.0 + + + +EU AI Act + + + +NIST AI RMF + + + +ICAO Doc 10019 + + diff --git a/diagrams/hero_banner_light.svg b/diagrams/hero_banner_light.svg new file mode 100644 index 0000000..b3a9120 --- /dev/null +++ b/diagrams/hero_banner_light.svg @@ -0,0 +1,26 @@ + + +GOPAL +GOPAL hero banner with logo, wordmark, tagline, and framework badges. + + + + + +GOPAL +The Rego policy library for AI compliance +94 policies · 15+ frameworks · Apache 2.0 + + + +EU AI Act + + + +NIST AI RMF + + + +ICAO Doc 10019 + + diff --git a/diagrams/logo_dark.svg b/diagrams/logo_dark.svg new file mode 100644 index 0000000..8872947 --- /dev/null +++ b/diagrams/logo_dark.svg @@ -0,0 +1,10 @@ + + +GOPAL +GOPAL mark — flat-top hexagon with code-braces glyph signalling policy-as-code. + + + + + + diff --git a/diagrams/logo_light.svg b/diagrams/logo_light.svg new file mode 100644 index 0000000..8e67d0d --- /dev/null +++ b/diagrams/logo_light.svg @@ -0,0 +1,10 @@ + + +GOPAL +GOPAL mark — flat-top hexagon with code-braces glyph signalling policy-as-code. + + + + + + diff --git a/diagrams/og_card.png b/diagrams/og_card.png new file mode 100644 index 0000000..ce99b1c Binary files /dev/null and b/diagrams/og_card.png differ diff --git a/diagrams/og_card_dark.svg b/diagrams/og_card_dark.svg new file mode 100644 index 0000000..00d4e6b --- /dev/null +++ b/diagrams/og_card_dark.svg @@ -0,0 +1,41 @@ + + +GOPAL — The Rego policy library for AI compliance +GOPAL social card with logo, wordmark, tagline, framework chips, and project URL. + + + + + + + + + + + +GOPAL + +The Rego policy library for AI compliance +94 policies · 15+ frameworks · 5 industries · Apache 2.0 + + + +EU AI Act + + + +NIST AI RMF + + + +ICAO Doc 10019 + + + ++13 more + + + +github.com/Principled-Evolution/gopal +94 Rego policies · Apache 2.0 + diff --git a/diagrams/og_card_light.svg b/diagrams/og_card_light.svg new file mode 100644 index 0000000..dcb6e4a --- /dev/null +++ b/diagrams/og_card_light.svg @@ -0,0 +1,41 @@ + + +GOPAL — The Rego policy library for AI compliance +GOPAL social card with logo, wordmark, tagline, framework chips, and project URL. + + + + + + + + + + + +GOPAL + +The Rego policy library for AI compliance +94 policies · 15+ frameworks · 5 industries · Apache 2.0 + + + +EU AI Act + + + +NIST AI RMF + + + +ICAO Doc 10019 + + + ++13 more + + + +github.com/Principled-Evolution/gopal +94 Rego policies · Apache 2.0 +