From 4e312f796785aa754034a968a7e76fe94ca496b6 Mon Sep 17 00:00:00 2001 From: Hardik Bhatia Date: Sat, 26 Sep 2026 21:31:40 +0530 Subject: [PATCH] chore: prepare beta release artifacts and launch documentation --- .github/workflows/publish-cli.yml | 22 ++++ .github/workflows/release.yml | 77 +++++++++++ CHANGELOG.md | 31 +++++ Dockerfile | 3 + LICENSE | 211 ++++++++++++++++++++++++++++-- NOTICE | 6 + README.md | 122 ++++------------- SECURITY.md | 4 +- apps/control-plane/package.json | 2 +- apps/dashboard/package.json | 2 +- apps/gateway/package.json | 2 +- docs/deployment.md | 44 +++++++ docs/launch-plan.md | 70 ++++++++++ docs/releases.md | 58 ++++++++ docs/roadmap.md | 80 +++-------- docs/validation.md | 89 +++++-------- package.json | 5 +- packages/cli/LICENSE | 211 ++++++++++++++++++++++++++++-- packages/sdk/LICENSE | 211 ++++++++++++++++++++++++++++-- packages/sdk/README.md | 2 +- scripts/release-artifacts.mjs | 35 +++++ sdks/python/LICENSE | 202 ++++++++++++++++++++++++++++ sdks/python/README.md | 2 +- sdks/rust/LICENSE | 211 ++++++++++++++++++++++++++++-- 24 files changed, 1427 insertions(+), 275 deletions(-) create mode 100644 .github/workflows/publish-cli.yml create mode 100644 .github/workflows/release.yml create mode 100644 CHANGELOG.md create mode 100644 NOTICE create mode 100644 docs/launch-plan.md create mode 100644 docs/releases.md create mode 100644 scripts/release-artifacts.mjs create mode 100644 sdks/python/LICENSE diff --git a/.github/workflows/publish-cli.yml b/.github/workflows/publish-cli.yml new file mode 100644 index 0000000..3f93f05 --- /dev/null +++ b/.github/workflows/publish-cli.yml @@ -0,0 +1,22 @@ +name: Publish CLI +on: + workflow_dispatch: +permissions: + contents: read + id-token: write +jobs: + publish: + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + environment: npm-release + steps: + - uses: actions/checkout@v7 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v7 + with: + node-version: 22 + registry-url: https://registry.npmjs.org + - run: pnpm install --frozen-lockfile + - run: pnpm check + - run: pnpm --filter @delvisor/pyro test:install + - run: pnpm --filter @delvisor/pyro publish --access public --provenance diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e5c7b46 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,77 @@ +name: Prepare release +on: + workflow_dispatch: + inputs: + publish_images: + description: Publish versioned containers and create a draft GitHub release + type: boolean + default: false +permissions: + contents: write + packages: write +concurrency: + group: release + cancel-in-progress: false +jobs: + prepare: + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + environment: release + timeout-minutes: 45 + steps: + - uses: actions/checkout@v7 + - uses: pnpm/action-setup@v4 + - uses: actions/setup-node@v7 + with: + node-version: 22 + - run: pnpm install --frozen-lockfile + - run: pnpm check + - run: pnpm evaluate + - run: pnpm --filter @delvisor/pyro test:install + - name: Read version + run: node -e 'const v=require("./package.json").version; if(!/^\d+\.\d+\.\d+(?:-[a-z0-9.]+)?$/.test(v)) process.exit(1); require("fs").appendFileSync(process.env.GITHUB_ENV,"RELEASE_VERSION="+v+"\n")' + - name: Refuse to overwrite an existing release + if: inputs.publish_images + env: + GH_TOKEN: ${{ github.token }} + run: | + if gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/v$RELEASE_VERSION" > /dev/null 2>&1; then + echo "This release tag already exists. Use a new version." + exit 1 + fi + - uses: docker/setup-qemu-action@v3 + - name: Build versioned images + env: + PUBLISH_IMAGES: ${{ inputs.publish_images }} + REGISTRY_TOKEN: ${{ github.token }} + run: | + docker buildx create --use + if [ "$PUBLISH_IMAGES" = true ]; then + echo "$REGISTRY_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin + fi + mkdir -p artifacts/image-metadata + for target in gateway control-plane dashboard; do + if [ "$PUBLISH_IMAGES" = true ]; then + docker buildx build --target "$target" --platform linux/amd64,linux/arm64 --push --provenance=mode=max --sbom=true --label "org.opencontainers.image.source=https://github.com/$GITHUB_REPOSITORY" --label "org.opencontainers.image.revision=$GITHUB_SHA" --tag "ghcr.io/delvisorlabs/pyro-$target:$RELEASE_VERSION" --metadata-file "artifacts/image-metadata/$target.json" . + else + docker buildx build --target "$target" --load --tag "pyro-$target:release-test" . + fi + done + - name: Collect immutable image digests + if: inputs.publish_images + run: | + node --input-type=module -e 'import fs from "node:fs"; const d={}; for(const t of ["gateway","control-plane","dashboard"]) d[t]=JSON.parse(fs.readFileSync(`artifacts/image-metadata/${t}.json`))["containerimage.digest"]; fs.writeFileSync("artifacts/digests.json",JSON.stringify(d));' + echo "RELEASE_IMAGE_DIGESTS=artifacts/digests.json" >> "$GITHUB_ENV" + - run: pnpm release:prepare + - uses: actions/upload-artifact@v7 + with: + name: pyro-release + path: artifacts/pyro-* + include-hidden-files: true + - name: Draft the release with verified artifacts + if: inputs.publish_images + env: + GH_TOKEN: ${{ github.token }} + run: | + tar -czf "artifacts/pyro-$RELEASE_VERSION.tar.gz" -C artifacts "pyro-$RELEASE_VERSION" + gh release create "v$RELEASE_VERSION" --draft --prerelease --target "$GITHUB_SHA" --title "Pyro $RELEASE_VERSION" --notes-file CHANGELOG.md "artifacts/pyro-$RELEASE_VERSION.tar.gz" "artifacts/pyro-$RELEASE_VERSION/compose.yaml" "artifacts/pyro-$RELEASE_VERSION/.env.example" "artifacts/pyro-$RELEASE_VERSION/SHA256SUMS" artifacts/pyro-*/delvisor-pyro-*.tgz diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..158fbf7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,31 @@ +# Changelog + +## 0.3.0-beta.1 — prepared, not yet published + +This beta adds policy revision history, drafts, pins and canary rollouts; an +application-scoped review inbox; versioned evaluation datasets and reports; +individual users, OIDC and audit history; and durable encrypted jobs with shared +quotas and retention. CLI 0.2.0 adds setup diagnostics and commands for the new +APIs. First-run examples use a local-only policy without a provider key. + +The release is intended for supervised pilots. A local 20-case regression +fixture passes; semantic attack detection has not been independently evaluated. + +### Upgrade notes + +- Back up PostgreSQL **and** `CONTROL_PLANE_SECRET` before upgrading. +- Existing profiles receive revision 1 at startup. Editing an existing policy + now requires its current `revision` in the payload; stale writes return 409. +- The bootstrap admin account remains available. New users receive only explicit + application grants. Management APIs now enforce roles. +- Job inputs have a 15-minute deadline; results and idempotency records remain + for 10 minutes after completion. Event retention defaults to 30 days. +- Reviews do not execute deferred actions. Semantic evaluations require explicit + consent and may incur provider charges. Dataset retention is chosen at import. +- Database changes and stored policy metadata are forward migrations. To revert + to an older server, restore the matching pre-upgrade database backup rather + than mixing old code with new policy metadata. + +See `docs/deployment.md` for backup, restore, retention and SSO setup. SDKs remain +source distributions. The release workflows prepare container images, a CLI +archive, checksums and a draft GitHub release; publication is a separate action. diff --git a/Dockerfile b/Dockerfile index c887600..6cd1e31 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,6 +26,7 @@ WORKDIR /app ENV NODE_ENV=production COPY --from=production-deps --chown=node:node /prod/gateway ./apps/gateway COPY --from=build --chown=node:node /app/profiles ./profiles +COPY --from=build /app/LICENSE /app/NOTICE /app/THIRD_PARTY_NOTICES.md ./ USER node EXPOSE 8080 CMD ["node", "apps/gateway/dist/server.js"] @@ -35,6 +36,7 @@ WORKDIR /app ENV NODE_ENV=production COPY --from=production-deps --chown=node:node /prod/control-plane ./apps/control-plane COPY --from=build --chown=node:node /app/profiles ./profiles +COPY --from=build /app/LICENSE /app/NOTICE /app/THIRD_PARTY_NOTICES.md ./ USER node EXPOSE 8081 CMD ["node", "apps/control-plane/dist/server.js"] @@ -42,6 +44,7 @@ CMD ["node", "apps/control-plane/dist/server.js"] FROM nginx:1.31-alpine AS dashboard COPY apps/dashboard/nginx.conf /etc/nginx/conf.d/default.conf COPY --from=build /app/apps/dashboard/dist /usr/share/nginx/html +COPY --from=build /app/LICENSE /app/NOTICE /app/THIRD_PARTY_NOTICES.md /usr/share/nginx/html/ RUN sed -i 's|^pid .*;|pid /tmp/nginx.pid;|' /etc/nginx/nginx.conf \ && sed -i '/^user nginx;/d' /etc/nginx/nginx.conf \ && chown -R nginx:nginx /var/cache/nginx /usr/share/nginx/html /etc/nginx/conf.d diff --git a/LICENSE b/LICENSE index a5f8133..d645695 100644 --- a/LICENSE +++ b/LICENSE @@ -1,17 +1,202 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ -Copyright 2026 Pyro contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..ec24a4b --- /dev/null +++ b/NOTICE @@ -0,0 +1,6 @@ +Pyro +Copyright 2026 Pyro contributors + +First-party source is Apache-2.0. Source-distributed UI components retain +their original licenses; see THIRD_PARTY_NOTICES.md. Dependency licenses +are distributed with their packages. diff --git a/README.md b/README.md index 97344cd..3b99918 100644 --- a/README.md +++ b/README.md @@ -18,105 +18,39 @@

Quick start · - Why Pyro? · + How it works · API reference

## What Pyro does -pyro_readme -
+Pyro is a self-hosted policy API and dashboard for teams adding LLM features or +tool-using agents. Call it before forwarding an untrusted prompt, retrieved +passage, or tool payload. It returns `allow`, `review`, or `block`; your application +must hold review decisions and reject blocked ones before executing work. -Pyro turns untrusted user input into explicit decisions: allow, review, or block. You configure what is evaluated, what each signal means, and which thresholds cause an intervention. +Local rules run on your server. Semantic detectors currently use **TypeSafe +System One** and send inputs to that provider. Your application's LLM can be from +any vendor, but the semantic classifier implementation is currently TypeSafe. +Pyro does not automatically intercept a model or tool call and cannot guarantee +that prompt injection will be detected. Keep authorization, tool permissions, +sandboxing and output validation in the application. -
+This is a beta for supervised pilots. The [evaluation guide](docs/evaluations/README.md) +contains a reproducible 20-case local-rule smoke test and its report. There is no +published independent semantic accuracy, false-positive or cross-vendor cost +benchmark. Provider charges depend on actual traffic and the provider's billing. -Each request follows a simple path: +## Operate and improve a policy -1. Application and profile local rules handle known cases immediately. No model involved. -2. If no local rule matches, Pyro evaluates enabled semantic detectors together in one System One request. -3. The selected protection profile combines the returned probabilities using thresholds and a decision strategy you control. -4. Pyro records the outcome, contributing signals, labels, and trace context so the decision can be understood later. +- Immutable policy history, draft/publish, explicit application pins and canaries. +- A labeled evaluation lab that compares published revisions using the gateway engine. +- A review inbox with assignment, comments, dispositions and signed callbacks. +- Individual accounts, OIDC, application-scoped roles and an audit history. +- Encrypted durable jobs, shared quotas, bounded fair scheduling and data retention. -The dashboard gives you one place to: - -- monitor prompt decisions in real time; -- search activity by application, outcome, policy, or custom label; -- define semantic detectors as plain-language questions; -- tune review and block thresholds without changing application code; -- compare new policies in shadow mode before enforcing them; -- add fast local rules for known phrases, values, or tool names; -- issue API keys and policies for different applications; -- inspect the rule or detector behind a decision; -- track model usage, cost, latency, and decision traces. - -Pyro records hashes and decision metadata unless raw storage is explicitly enabled. - -## Why Pyro? - -Most prompt-security products give you a fixed detector, a collection of scanners, or a framework that becomes part of the application runtime. Pyro focuses on: **visible, configurable protection that operators and developers can work on together**. - -A protection profile is not a hidden vendor policy. It is a configuration you can open and change: detectors, questions, weights, thresholds, decision strategy, failure behavior, notifications, and shadow profiles. Local rules are visible on the application or profile that owns them. Results show the signals that contributed to the final action. - -System One models are designed to return typed decisions and calibrated probabilities instead of generated prose. Pyro uses that shape directly: all enabled detectors are evaluated together, and the result is immediately usable by software and visible to operators. - -This creates a practical evaluation cascade: - -```text -request - ├─ known local rule ───────────────→ decide locally (no model cost) - └─ no local match - └─ semantic detectors ────────→ one System One request - └─ profile thresholds ──→ allow, review, or block -``` - -You can keep simple checks fast and deterministic while reserving model analysis for ambiguity and context. The result is not merely a risk score: it is a decision tied to the exact configuration that produced it. - -### Cost of analyzing prompts - -Prompt monitoring becomes much less useful when cost forces you to sample only a small part of your traffic. Pyro sends all enabled detector questions in one System One request instead of making a separate generative-model call for every check. - -The following estimate uses public list prices checked on September 22, 2026. To make different billing units comparable, it assumes **1 million input analyses**, each containing **1,000 tokens (about 4,000 characters)**, with no response scanning. That is 1 billion analyzed input tokens in total. - -| Analyzer | Public billing basis | Estimated analysis cost | Cost vs. Pyro | What the estimate covers | -| --- | --- | ---: | ---: | --- | -| **Pyro with [Jev](https://typesafe.ai/)** | $0.042 per million input tokens; output decisions are not metered | **$42.00** + Pyro infrastructure | **1×** | One Jev request returning every enabled detector probability. The 1,000-token allowance must include Pyro's detector questions as well as the input. | -| [Google Cloud Model Armor](https://cloud.google.com/security/products/model-armor) | First 2 million tokens each month are free, then $0.10 per million tokens | **$99.80** | **2.38×** | Input screening only. Google meters the combined prompt and response tokens when both are screened. | -| [Amazon Bedrock Guardrails](https://aws.amazon.com/bedrock/pricing/) | Prompt-attack filter via `InvokeGuardrailChecks`: $0.08 per 1,000 text units; one text unit is up to 1,000 characters | **$320.00** | **7.62×** | The prompt-attack filter only. Content, sensitive-information, and other filters are charged separately. | -| [Check Point AI Guardrails / Lakera Guard](https://docs.lakera.ai/docs/api) | Public product documentation; [pricing is sales-quoted](https://www.checkpoint.com/about-us/contact-us/) | **Not publicly calculable** | — | Managed prompt and agent screening. Check Point does not publish a self-serve usage rate. | -| [Protect AI LLM Guard](https://protectai.github.io/llm-guard/) | Open-source software; you supply the compute for each configured scanner | **Deployment-dependent** | — | Model hosting, CPU/GPU time, and operations. Multiple scanners run individually, so cost depends on the selected set and hardware. | -| [NVIDIA NeMo Guardrails](https://docs.nvidia.com/nemo/guardrails/latest/home) | Open-source framework; configured models and services supply the inference | **Deployment-dependent** | — | Model/API calls and infrastructure used by the selected rails. The framework itself is not a metered prompt-analysis service. | - -Under these assumptions, Pyro's external analysis charge is about **58% lower than Model Armor** and **87% lower than Bedrock's prompt-attack filter**. - -The arithmetic is based on each vendor's billing meter, not a claim that the products provide identical detection quality or coverage. [Google documents](https://docs.cloud.google.com/model-armor/overview#tokens) roughly four characters per token; AWS bills each 4,000-character input as four text units. The Google estimate subtracts its 2-million-token monthly free tier. Taxes, commitments, logging, networking, Pyro hosting, and storage are excluded. Prices change, so verify the linked vendor pages before budgeting. - -TypeSafe separately reports up to **444.6× lower cost** and **193.6× faster execution** in its [System One workflow evaluations](https://typesafe.ai/blog/introducing-system-one-models-and-jev). Those are vendor-run workflow benchmarks against generation models—not head-to-head tests against Google Model Armor, Bedrock Guardrails, or Lakera—so they are not used in the table above. No cross-vendor quality score is presented here because the available public results do not test every product against the same attacks, policy, traffic, and billing boundaries. - -### How the products differ - -| Existing approach | What it is designed for | When Pyro is the better fit | -| --- | --- | --- | -| [Lakera Guard / Check Point AI Guardrails](https://docs.lakera.ai/docs/prompt-defense) | A managed security product with built-in prompt-attack detection and enforcement. | You want to self-host the monitoring and policy layer, define organization-specific signals, and keep searchable history in your own PostgreSQL database. | -| [Google Cloud Model Armor](https://cloud.google.com/security/products/model-armor) and [Amazon Bedrock Guardrails](https://aws.amazon.com/bedrock/guardrails/) | Managed cloud controls with vendor-defined detectors and integrations. | You want provider-independent application profiles, visible detector questions and thresholds, and a dashboard you operate yourself. | -| [Protect AI LLM Guard](https://protectai.github.io/llm-guard/get_started/quickstart/) | A Python toolkit of individual input and output scanners for concerns such as prompt injection, toxicity, secrets, and anonymization. | You want a language-agnostic HTTP service, application-level policies, and operational history rather than coordinating scanner models inside a Python application. | -| [NVIDIA NeMo Guardrails](https://docs.nvidia.com/nemo/guardrails/latest/home) | A broad Python framework for programmable input, output, retrieval, dialog, and execution rails. | You need focused prompt monitoring and explicit allow/review/block decisions without introducing a conversation runtime or guardrail configuration language. | - -These products are not exact substitutes. LLM Guard is a stronger match when you need local PII transformation or many specialized scanners. NeMo Guardrails is a stronger match when you need to control an entire conversation or agent workflow. A managed cloud service may be the easiest choice when all of your inference already lives with that provider. Pyro is strongest when prompt visibility, organization-specific detection, cost control, and editable policy are the priority. - -## Configurations are part of the product - -Pyro treats protection as configuration rather than magic hidden behind an API. New profiles begin empty, so an application receives only the checks its team deliberately chooses. Teams can start narrowly, inspect real decisions, adjust thresholds, and test a replacement profile in shadow mode before enforcing it. - -The **rule and profile library** in [`profiles/`](./profiles/README.md) provides four opt-in YAML presets. Import, export, inspect and edit them from Protection Profiles. Reusable protection packs remain: - -- opt-in rather than silently installed; -- readable before they are enabled; -- forkable and editable for each organization; -- stored as readable YAML so changes can be reviewed in source control; -- validated on import, with coverage evaluated against your own traffic. - -The goal is not a marketplace of opaque promises. It is a practical catalog of configurations that teams can understand, adapt, and improve. +See [deployment and data retention](docs/deployment.md), [release/support notes](docs/releases.md), +[security reporting](SECURITY.md), and [license notices](THIRD_PARTY_NOTICES.md). ## Quick start @@ -245,7 +179,7 @@ const decision = await pyro.classify( { labels: { environment: "production" } }, ); -if (decision.action === "block") { +if (decision.action !== "allow") { throw new Error(decision.reason); } ``` @@ -268,7 +202,7 @@ decision = pyro.classify( labels={"environment": "production"}, ) -if decision["action"] == "block": +if decision["action"] != "allow": raise RuntimeError(decision["reason"]) ``` @@ -286,7 +220,7 @@ An async Rust client is available in [`sdks/rust`](./sdks/rust/README.md), with - Profiles and integrations contract: [`docs/control-plane.openapi.yaml`](./docs/control-plane.openapi.yaml) - Prometheus metrics: `http://localhost:8080/metrics` -Configuration, policies, sessions, and activity are stored in PostgreSQL. Provider credentials entered through the dashboard are encrypted before storage. Prompt content sent for System One evaluation is transmitted to the configured model provider; review that provider's data terms for your deployment. Pyro does not store raw inputs unless a protection profile enables previews. +Configuration, policies, sessions, and activity are stored in PostgreSQL. Provider credentials entered through the dashboard are encrypted before storage. Prompt content sent for System One evaluation is transmitted to the configured model provider; review that provider's data terms for your deployment. Synchronous classifications omit raw input previews unless the policy enables them. Durable jobs temporarily retain encrypted inputs, and evaluation datasets retain encrypted inputs for the explicitly selected period. Caller metadata and labels are also stored with events; keep secrets out of them. See the retention controls in the deployment guide. ## Development @@ -299,9 +233,9 @@ PYTHONPATH=sdks/python/src python3 -m unittest discover -s sdks/python/tests -v Security issues should be reported privately as described in [`SECURITY.md`](./SECURITY.md). -## Next features +## Feature status -See the [five-feature roadmap](./docs/roadmap.md) for versioned policies, an evaluation lab, a review inbox, team access, and durable execution/operational controls. +See [feature status and follow-ups](./docs/roadmap.md) for the implemented beta workflows and remaining scale/measurement work. ## Scope diff --git a/SECURITY.md b/SECURITY.md index 45941fb..61e34f4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,6 +4,8 @@ Pyro processes untrusted content and may sit in front of privileged AI agents. S Please do not open a public issue for a suspected vulnerability. Use GitHub's **Report a vulnerability** button in the repository Security tab to submit a private advisory with reproduction steps, affected versions, and potential impact. -The project currently supports the latest release on the `main` branch. Maintainers will acknowledge a complete report as soon as practical and coordinate disclosure after a fix is available. +During beta, fixes target the newest published beta release. The `main` branch is development code. See [releases and support](docs/releases.md). Maintainers will acknowledge a complete report as soon as practical and coordinate disclosure after a fix is available. Before exposing Pyro outside localhost, use unique credentials, terminate TLS at a hardened ingress, restrict the management interface, and configure PostgreSQL backups. + +See [deployment and data flow](docs/deployment.md) for TypeSafe egress, raw-input retention, encryption, roles, and operational limits. Pyro has not undergone an independent security audit. diff --git a/apps/control-plane/package.json b/apps/control-plane/package.json index d86e601..80ce067 100644 --- a/apps/control-plane/package.json +++ b/apps/control-plane/package.json @@ -1,6 +1,6 @@ { "name": "@pyro/control-plane", - "version": "0.2.0", + "version": "0.3.0-beta.1", "private": true, "type": "module", "main": "dist/server.js", diff --git a/apps/dashboard/package.json b/apps/dashboard/package.json index 0c5c536..0fc0e2f 100644 --- a/apps/dashboard/package.json +++ b/apps/dashboard/package.json @@ -1,6 +1,6 @@ { "name": "@pyro/dashboard", - "version": "0.2.0", + "version": "0.3.0-beta.1", "private": true, "type": "module", "scripts": { diff --git a/apps/gateway/package.json b/apps/gateway/package.json index b6b6d37..420a57f 100644 --- a/apps/gateway/package.json +++ b/apps/gateway/package.json @@ -1,6 +1,6 @@ { "name": "@pyro/gateway", - "version": "0.2.0", + "version": "0.3.0-beta.1", "private": true, "type": "module", "main": "dist/server.js", diff --git a/docs/deployment.md b/docs/deployment.md index ab9651d..8186cff 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -90,3 +90,47 @@ removes stored inputs; an in-flight provider request can still finish. A selecte provider credential is encrypted in the run until completion or expiry so a resumed run uses the authorized account. Keep reports and dataset snapshots in your own controlled storage when longer retention is required. + +## Backup, restore and upgrades + +Use the same PostgreSQL major version for this procedure. Before an upgrade, +pause incoming classification traffic and workers, save the deployment files, +and copy `.env` into your encrypted secret backup. Keep `CONTROL_PLANE_SECRET` +with that backup; the SQL dump alone cannot recover encrypted credentials or +queued inputs. Run from the configured compose directory: + +```sh +docker compose stop gateway control-plane dashboard +# Restrict access to the resulting backup; it contains configuration and events. +umask 077 +docker compose exec -T postgres pg_dump -U pyro -d pyro -Fc > pyro-backup.dump +``` + +Restore into a **separate empty database** and test it before replacing a running +installation. The target command below restores into `pyro_restore`, never over +the live `pyro` database: + +```sh +docker compose exec -T postgres createdb -U pyro pyro_restore +docker compose exec -T postgres pg_restore -U pyro -d pyro_restore --exit-on-error < pyro-backup.dump +``` + +Start an isolated stack pointed at the restored database with the matching +secret and image versions. Verify sign-in, policy hashes, application keys, +retained events and a local classification. Keep queues and webhook destinations +paused or redirected during a restore drill to avoid replaying external work. +After validating the new release, resume the original stack. Do not run +`docker compose down --volumes` during an upgrade. Restoring older code requires +the corresponding pre-upgrade database, not only an image rollback. + +## Pilot operating targets + +Use local-only load tests first. Measure p50/p95 latency, queue age, error rate, +provider failures and webhook backlog on the actual deployment; no universal +latency or throughput SLA is claimed. Alert on persistent job failures, growing +queue age, a provider circuit staying open, or webhook failures. `/v1/health` +reports durable queue counts and oldest age; `/metrics` exposes gateway metrics; +Webhooks shows delivery history. Keep one gateway/control-plane replica for an +initial pilot, then test shared PostgreSQL quotas and worker recovery before +scaling. The bounded document queue and audit/history documents are deliberately +suited to pilot volumes, not an unmeasured high-volume service. diff --git a/docs/launch-plan.md b/docs/launch-plan.md new file mode 100644 index 0000000..b9fe743 --- /dev/null +++ b/docs/launch-plan.md @@ -0,0 +1,70 @@ +# Launch and first-user plan + +## Who this beta is for + +Start with developers operating a self-hosted support assistant or internal agent +who need visible application policies and decision traces. The initial promise +is a working policy workflow they can inspect and tune. Avoid claiming that a +classifier makes arbitrary agents safe or that local smoke-test success proves +semantic prompt-injection coverage. + +## Pilot before ads + +Recruit five volunteer teams through existing developer relationships, relevant +open-source issue discussions where a maintainer invites solutions, and technical +communities whose rules permit product introductions. Do not mass-message users, +scrape addresses, or post automated endorsements. Ask about their existing +problem before proposing Pyro. Offer help with one staging integration and a +redacted evaluation dataset. No messages or posts have been sent by this change. + +Count activation when a team independently starts Pyro, gets an expected local +decision, connects one application, and returns to review/evaluate another batch. +Measure time to first decision, install failures, weekly active applications, +review dispositions and whether someone continues after the assisted session. +Collect these by consent in pilot check-ins; the server has no added phone-home +telemetry. Do not turn downloads or GitHub stars into a retention claim. + +Suggested pilot invitation for a human to adapt: + +> I'm building Pyro, a self-hosted policy API for prompts and agent tool inputs. +> It has local rules, optional TypeSafe classification, decision traces and a +> workflow for evaluating policy changes. I'm looking for developers willing to +> try one staging integration and tell me where it fails. Would a short setup +> session help with a problem you're already trying to solve? + +## Public launch assets + +Publish a versioned beta release, an anonymous-pull installation path, a short +screen recording of the local quickstart, the reproducible evaluation report, +data-flow/retention documentation, limitations and a maintainer contact. Demo +allow, review and block outcomes and a provider configuration failure. Show that +review pauses application execution rather than silently proceeding. + +Launch a technical write-up explaining one real integration and its measured +failure cases. Consider Show HN only after anyone can try the product immediately; +write the post personally and follow its current rules. Ask relevant Reddit or +Discord moderators before posting when promotion rules are unclear. Post useful +findings and a working example, not repeated launch links. A GitHub discussion +and a changelog can keep early adopters informed without unsolicited messages. + +## ₹10,000 advertising budget + +Hold the budget until at least three pilot teams activate and two return the +following week. These are proposed decision criteria, not observed traction. +If organic activation works, spend ₹2,000 on a narrowly targeted developer test +with one clear landing page and consent-respecting conversion measurement. Judge +cost per activated integration, not click-through rate. Stop if clicks do not +lead to independent setup; fix the funnel before spending more. Only expand to +another ₹3,000 after the first cohort returns. Keep ₹5,000 for the channel that +produces retained users. No campaigns are created or spend authorized by this file. + +## Release checklist + +- Merge the reviewed changes; publish the CLI and versioned server images. +- Verify the website downloads reference the released commit or image digests. +- Run an anonymous clean-machine install and a database restore drill. +- Confirm the real deployment's SSO callback, credentials and data terms. +- Run a representative semantic benchmark with an explicitly authorized key and + paid budget before making accuracy or cost comparisons. +- Interview pilot users and publish only claims supported by their permission + and recorded results. diff --git a/docs/releases.md b/docs/releases.md new file mode 100644 index 0000000..ecc77c4 --- /dev/null +++ b/docs/releases.md @@ -0,0 +1,58 @@ +# Releases and support + +Pyro is beta software maintained by [Delvisor Labs](https://github.com/DelvisorLabs). +Report reproducible issues in [GitHub Issues](https://github.com/DelvisorLabs/Pyro/issues) +and private vulnerabilities through [GitHub Security](https://github.com/DelvisorLabs/Pyro/security/advisories/new). +Contact [hello@delvisor.com](mailto:hello@delvisor.com) for a supervised pilot. +There is no paid support SLA or independently verified detection guarantee. + +## Preparing a release + +`pnpm check`, the PostgreSQL tests, the local evaluation budget, and the packed +CLI installation smoke test must pass. Set a new root version and app versions, +update `CHANGELOG.md`, and merge the reviewed changes. Run **Prepare release** on +`main` with publication disabled first. It builds all three containers and +uploads installation artifacts without publishing them. + +When ready, run it with `publish_images` enabled. It publishes amd64/arm64 images +with build provenance and SBOMs, generates a compose file pinned to the returned +image digests, and creates a **draft** GitHub release with a CLI archive and +checksums. It refuses an existing release tag. Configure the GitHub `release` +environment with the appropriate maintainers/reviewers. Check GHCR package +visibility is public and test an anonymous pull before publishing the draft. +Do not point website installation links at an unpublished release. + +For local artifact inspection after a build: + +```sh +pnpm release:prepare +# Image names in this local output are placeholders until the images exist. +``` + +The published archive contains compose.yaml, .env.example, profiles, CLI .tgz, +license notices, deployment notes, release metadata and SHA256SUMS. Extract it in +an empty directory and run `sha256sum -c SHA256SUMS` (or `shasum -a 256 -c +SHA256SUMS` on macOS) before configuring credentials. Digest-pinned images require +no repository checkout or local application build. + +## Publishing the CLI + +Configure the npm package's trusted publisher for `DelvisorLabs/Pyro`, workflow +`publish-cli.yml`, environment `npm-release`, and configure that GitHub environment. +The **Publish CLI** workflow runs only on main, verifies the build and packed +installation, then uses pnpm with OIDC provenance. No long-lived npm token is +stored in the repository. Ensure the CLI version is new before running it. +See the [npm trusted publishing guide](https://docs.npmjs.com/trusted-publishers/) +and [pnpm publishing reference](https://pnpm.io/cli/publish). + +A prepared PR, container build, or local package archive is not a published +release. Confirm the npm page, GitHub release and anonymous container pulls after +publication, then update website links and the compatibility notes together. + +## Support policy + +During beta, fixes target the newest published beta. main is development code, +not a release channel. Pin the CLI version, server image digest, PostgreSQL major +version and policy revision in deployments. Keep the previous release archive +and a tested backup before upgrades. Breaking changes are called out in the +changelog; no long-term support window is promised yet. diff --git a/docs/roadmap.md b/docs/roadmap.md index 755e620..33cc688 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,63 +1,17 @@ -# Five next features for Pyro - -These proposals follow the current architecture: Fastify gateway/control plane, PostgreSQL documents and events, an in-process classification queue, a React dashboard, and the new profiles/outbound-delivery layer. They are recommendations, not functionality implemented in this change. - -## 1. Versioned policies, staged rollout and rollback - -**Why:** profiles currently update in place (`apps/control-plane/src/app.ts`). Events identify a profile but do not preserve the exact revision that made the decision. Editing a threshold can make a historical decision impossible to reproduce. - -**Build:** immutable profile revisions and content hashes; draft/published states; semantic diffs for thresholds, detectors and local rules; application bindings to an explicit revision; shadow/canary rollout; one-click rollback; an audit record of who published each change. Include the application rule revision in the decision snapshot, since application rules combine with profile rules. - -**First release:** create a new revision on every save, store the revision/hash on events, and allow an application to pin or roll back a revision. Add approval gates after multi-user access exists. - -**Acceptance:** replay a stored test input with its original config even after later edits; rollback without rewriting history; concurrent edits cannot silently overwrite one another. Profile export includes a portable revision/hash but excludes deployment secrets. - -**Priority:** highest. This makes every subsequent tuning feature safer and makes decision traces trustworthy. - -## 2. Evaluation and regression lab - -**Why:** the playground classifies individual requests and shadow mode compares actions, but there is no repeatable dataset workflow for measuring false positives, misses or policy regressions. Curated profiles are currently starting points without measured coverage claims. - -**Build:** versioned labeled datasets; batch evaluation against multiple policy revisions; precision/recall and confusion matrices per attack class; disagreements with ground truth; p50/p95 latency, token cost and local-rule hit rate; threshold sweeps; CI gates before publishing profiles. Let operators add redacted Activity samples to a dataset with an explicit retention decision. Record provider/model version where available. - -**First release:** import a JSONL dataset with expected allow/review/block outcomes, compare two revisions, and export the report. Reuse the gateway's evaluation path so the lab cannot drift from enforcement. - -**Acceptance:** reproducible dataset/config hashes, no hidden provider calls for local-only runs, clear cost estimates before a batch, cancellation and resumption, and a CI failure when a configured regression budget is exceeded. - -**Priority:** highest alongside versioning. It establishes whether Pyro is getting better rather than simply blocking more traffic. - -## 3. A human review inbox with feedback - -**Why:** `review` is a decision and dashboard notification today. It has no owner, resolution, service-level target or feedback loop. An alert can tell a team something happened without helping them resolve it. - -**Build:** a triage queue with assignment, severity, comments, disposition (true positive, false positive, uncertain), saved filters and aging indicators. Link events by trace/application and group related alerts. Emit signed resolution callbacks so an application can implement a delayed-approval flow when appropriate. Keep the original decision immutable and store review as a separate record. - -**First release:** persistent disposition and assignment in Activity, grouped notifications, and export of reviewed samples to the evaluation lab. Add authenticated review workflows once permission scoping and audit records are in place. - -**Acceptance:** each resolution is attributed and auditable; duplicate clicks do not produce conflicting outcomes; reviewers only access authorized applications; resolving a record does not silently execute a previously blocked tool call. - -**Priority:** next. Converts alerts into an operational workflow and produces useful training/evaluation feedback. - -## 4. Team access: SSO, application-scoped roles and audit logs - -**Why:** the control plane uses one administrator password and session authentication. A role field exists, but there is no complete role-enforcement model for managing profiles, keys, integrations or sensitive previews. - -**Build:** OIDC SSO, individual accounts, admin/operator/reviewer/viewer roles, application-level grants, service accounts, session revocation and expiration, scoped key rotation, and append-only audit records. Gate viewing raw previews separately from policy editing. Audit integration destination changes and signing-key rotations without recording secrets. - -**First release:** individual users plus explicit server-side permission checks and an audit log. Add OIDC next; introduce organizations/tenant isolation only when deployment requirements justify the additional data-model complexity. - -**Acceptance:** unauthorized mutations fail in the API even when the UI is bypassed; revoked sessions stop working; one application's users cannot list another application's events or secrets; every privileged change has actor, timestamp and before/after revision identifiers. - -**Priority:** required before wider team adoption or hosted multi-tenant operation. - -## 5. Durable execution and operational controls - -**Why:** classification jobs and rate-limit counters currently live in gateway memory (`jobs` and `rateLimits` in `apps/gateway/src/app.ts`). Restarting loses pending job state; multiple replicas have independent quotas. Event/delivery history currently has no automatic retention policy. - -**Build:** durable classification job state with worker leases, idempotency keys and result TTL; distributed application quotas; queue backpressure and fair scheduling across applications; configurable data retention/deletion; outbox retention and delivery backlog metrics; end-to-end OpenTelemetry traces; documented SLOs, backup/restore and load-test targets. - -**First release:** durable jobs plus distributed limits and retention controls. Reuse the outbox lease pattern but keep classification workers and notification workers on independent capacity budgets. Store raw job inputs encrypted with short lifetimes because durable evaluation requires retaining inputs while queued. - -**Acceptance:** restart workers during a load test without losing accepted jobs; honor one quota across replicas; prevent one application starving others; expire stored inputs on schedule; expose queue age and delivery failure SLOs; demonstrate a tested restore procedure. Idempotency semantics must distinguish duplicate API submissions from at-least-once upstream execution after a crash. - -**Priority:** before substantial traffic or horizontal scaling. This is the largest operational reliability gain after durable notification delivery. +# Feature status + +The five roadmap areas have a working beta implementation in this release. +They remain subject to the pilot limits below; a dashboard control is not a +claim of independent security validation or unlimited scale. + +| Area | Implemented | Further work | +| --- | --- | --- | +| Policy changes | Immutable revisions and hashes; draft/publish; stale-edit conflicts; app pins; canary selection; rollback by publishing old configuration; event revision and application-rule snapshot | Approval gates and richer visual field-by-field diffs | +| Evaluation lab | Encrypted versioned JSONL datasets; one/two-revision comparison; shared gateway engine; hashes; metrics and category confusion matrices; paid consent; cancel/resume; reports and local CI budgets | Representative held-out semantic benchmarks, threshold sweeps, larger datasets | +| Review inbox | Scoped triage, assignment, severity, comments, dispositions, aging, saved status filter, trace context, revision conflicts, signed callbacks and explicit JSONL sample export | Rich saved filters, automated alert grouping and case management | +| Team access | Individual password accounts, OIDC, admin/operator/reviewer/viewer roles, application grants, preview permission, session revocation, scoped service keys and audit intents/outcomes | Organizations/multi-tenant hosting and tamper-evident external audit storage | +| Durable execution | Encrypted pending inputs; PostgreSQL worker leases; idempotent submissions; shared quotas; bounded fair scheduling; TTLs; retention; queue status; backup/restore procedure | Row-level high-throughput queues, end-to-end OpenTelemetry spans, measured production SLOs | + +Use the [deployment guide](deployment.md), [evaluation guide](evaluations/README.md) +and [release guide](releases.md) before a pilot. Unmeasured accuracy and throughput +must not be presented as demonstrated product guarantees. diff --git a/docs/validation.md b/docs/validation.md index a06bf8a..707a309 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -1,58 +1,31 @@ -# Validation for the dashboard, profiles, outgoing webhooks and SDKs - -Webhook form follow-up (2026-09-23): - -- Replaced comma-separated resource IDs with named, searchable application/profile checklists built from shadcn/ui Radix primitives. Added field help, explicit All scopes, inline risk/action validation and loading/retry feedback. -- Dashboard tests: 12 passed. New coverage checks ID serialization, explicit wildcard selection, preservation of unavailable saved references and disabled webhook state, unchanged destination handling when editing, and risk/action validation. Dashboard production build and whitespace checks passed. -- Verified live application/profile choices, search with and without matches, multiple selection, keyboard toggling, Escape dismissal, focus return and minimum-risk help on localhost. Clearing the final specific selection disables Save. Verified the migrated shared checkbox on Applications without saving changes. -- Checked both themes and a 390px viewport. Corrected nested dialog scrolling so only the form body scrolls; header/footer and checklist contents stay within the viewport. Restored light mode and desktop size, and cancelled test drafts without creating a webhook. -- Restarted Vite on `127.0.0.1:3000` to clear stale imports after adding dependencies. No new runtime errors were observed after restart. - -Webhook presentation follow-up (2026-09-23): - -- Renamed product copy and navigation references to Webhooks across the dashboard, website and guides; retained technical descriptions of outgoing delivery. -- Removed the local receiver help panel. Delivery history now uses the card width, separates timestamps, labels HTTP responses, shows status badges and only includes an Action column when a delivery can be retried. -- Dashboard and website production builds passed, along with `git diff --check`. Verified Refresh, Add webhook, light/dark presentation and a 390px viewport against existing local delivery history. The table scrolls inside its card without page overflow; no browser errors or warnings were observed. -- Restored light mode and the desktop viewport. Restarted the standalone website on `127.0.0.1:3100` and verified its updated home and documentation copy. All services remain local. - -Settings, navigation and library follow-up (2026-09-23): - -- Dashboard tests: 8 passed, covering preference migration/validation, library filtering and response defaults, stable detector identity, and historical API response handling. Production dashboard build and whitespace checks passed. -- Verified all six dashboard preference controls, persistence after reload, reset to defaults, System theme selection, compact table cell padding, full Activity timestamps and the neutral-black dark palette (`#050505` canvas). The existing classifier settings remain available separately. -- Verified the restored dropdown opening animation and 180ms sliding highlight, arrow-key selection and focus return inside a profile dialog. Reduced motion suppresses transitions. -- Verified profile library text search, local-only filtering, empty results, YAML inspection and customization into an editable draft. Cancelled the draft without modifying saved policies. -- Verified Playground is under Observe, there is no Test group, Settings has a separate sidebar entry and sidebar hover fills are removed. -- Settings and the library fit a 390px viewport without page overflow. Restored the desktop viewport and default personal preferences after testing. Everything remains on localhost. - -Dashboard redesign verification (2026-09-23): - -- Dashboard unit tests: 4 passed, including detector editor identity and payload serialization. The editor-only row key stays stable while its API ID changes and is omitted from saves. -- Production dashboard build and `git diff --check`: passed. -- Verified continuous character-by-character typing in both a new detector and an existing detector on `localhost:3000`; full values appeared and focus stayed in the ID input. Cancelled both drafts without modifying saved policies. -- Verified shared dropdown keyboard selection and focus restoration inside the profile dialog. Confirmed Activity filters and request trace dialogs still work. -- Verified neutral light and dark themes, self-hosted Open Sans, themed charts/dialogs, and dark preference persistence after reload. Returned the dashboard to light mode. -- Navigated all nine dashboard pages successfully. A fresh final reload produced no browser console errors or warnings. -- At a 390px viewport, checked collapsible navigation, profile dialogs, Overview, Usage, Applications, Activity and outgoing webhooks. Corrected Applications overflow; those pages fit the viewport, with tables scrolling within their containers. Restored the desktop viewport afterward. - -The shared UI conventions and repeatable browser checks are documented in `apps/dashboard/README.md`. - -Latest local verification (2026-09-23): - -- Reproduced the Protection Profiles white screen on the actual `localhost:3000` dashboard: older backend records omitted `localRules`. Schema defaults now normalize those records before rendering/editing. A page error boundary keeps navigation available if any page fails. -- Verified Activity against the existing database: the list, filters and an existing request trace render. Historical traces without detector arrays and responses without label catalogs have regression coverage; failed requests are shown in the page. -- Verified existing profile cards, the existing profile editor, all four curated presets, outgoing webhook configuration and delivered history in the browser after updating the running services. -- `npm run typecheck`: passed. -- `npm test` with `TEST_DATABASE_URL` pointing to an isolated PostgreSQL 17 instance: 42 tests passed, none skipped. This includes three dashboard compatibility regressions and a worker test ensuring unsupported persisted destinations cannot enqueue or send. -- `docker compose build gateway control-plane`: passed, including all package/application production builds. Both containers were recreated from the new images and report healthy. The existing Vite dashboard remains on port 3000; PostgreSQL data was retained. -- `npm run test:webhook` against the actual local Docker gateway/control plane: passed. Verified HMAC on `integration.test` and a real local-rule `decision.created` event; a deliberate HTTP 503 caused a retry and HTTP 204 completed delivery. Temporary destination/profile removed; audit records retained. All traffic stayed local, with no model request. -- The standalone website passed its Next.js production build and was restarted on `127.0.0.1:3100` with outgoing-webhook-only copy. -- `git diff --check`: passed. - -Earlier verification for the unchanged SDK/profile work: - -- PostgreSQL checks cover atomic event/outbox writes, duplicate suppression, concurrent claims, expired leases, stale-worker acknowledgements, manual retry and rollback on an invalid delivery. -- Rust SDK: four tests and Clippy with warnings denied passed. Existing Python SDK test passed. -- TypeScript SDK/contracts packed and installed in a separate temporary consumer; imports and a request succeeded. -- Website desktop/mobile layouts, interactive examples, documentation navigation and YAML downloads checked. - -The optional observability overlay and non-webhook adapter have been removed. Neither SDK has been published. The website now lives in the sibling `website` directory alongside Delvisor's homepage, with Pyro at `/pyro` and its quickstart at `/pyro/docs`. +# Beta validation record + +Validated locally on 26 September 2026 for the proposed server 0.3.0-beta.1 and +CLI 0.2.0 changes. These checks are engineering evidence for a supervised pilot, +not an independent security audit or a semantic detection benchmark. + +- Full workspace type checks, tests and production builds passed, including + PostgreSQL storage, concurrency, scoped access, OIDC signed-token/nonce/replay + tests, review conflicts and signed resolution callbacks. +- The CLI archive installed outside the repository and ran successfully. +- Python and Rust SDK tests passed. The dependency audit reported no known high + severity vulnerabilities at the time of the check. +- A fresh four-service Docker stack reached healthy state without startup + restarts. Local-only synthetic inputs returned allow, block and review. +- The evaluation service ran all 20 local smoke cases with their expected actions + against PostgreSQL. This verifies specified local rules only. +- Ten accepted asynchronous jobs survived a forced gateway SIGKILL and restart. + Matching idempotency retries returned the original ID; changed input returned + 409. This used a local fake provider; no external model calls were made. +- A PostgreSQL dump restored into a separate empty database retained policy + hashes and all events. Isolated services using that restored database accepted + the administrator login and existing application key and classified locally. +- Browser checks covered CLI/Docker switching, the Docker symbol, narrow-screen + documentation, evaluation reports, review results and policy-history controls. + The website passed lint and its production build. + +Still required per deployment: an actual identity-provider/proxy smoke test, +representative semantic evaluation with explicit provider-cost authorization, +load testing at intended traffic, and verification of published artifacts after +release. Release workflows are prepared; this record does not assert that an npm +version, container image, GitHub release or website deployment was published. diff --git a/package.json b/package.json index 53d876f..3537aa7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pyro", - "version": "0.2.1", + "version": "0.3.0-beta.1", "private": true, "type": "module", "scripts": { @@ -13,7 +13,8 @@ "webhook:receiver": "node scripts/webhook-receiver.mjs", "test:webhook": "node scripts/test-webhook.mjs", "pyro": "node packages/cli/dist/bin.js", - "evaluate": "node scripts/evaluate.mjs" + "evaluate": "node scripts/evaluate.mjs", + "release:prepare": "node scripts/release-artifacts.mjs" }, "devDependencies": { "concurrently": "^9.2.1", diff --git a/packages/cli/LICENSE b/packages/cli/LICENSE index a5f8133..d645695 100644 --- a/packages/cli/LICENSE +++ b/packages/cli/LICENSE @@ -1,17 +1,202 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ -Copyright 2026 Pyro contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/sdk/LICENSE b/packages/sdk/LICENSE index a5f8133..d645695 100644 --- a/packages/sdk/LICENSE +++ b/packages/sdk/LICENSE @@ -1,17 +1,202 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ -Copyright 2026 Pyro contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/sdk/README.md b/packages/sdk/README.md index e050a1f..4fbde3f 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -14,7 +14,7 @@ const decision = await pyro.classify({ labels: { session_url: "https://support.example/chats/123", tenant: "acme" }, }); -if (decision.action === "block") throw new Error(decision.reason); +if (decision.action !== "allow") throw new Error(decision.reason); ``` The API key selects the application and its policy/rules; an application ID is never trusted from request data. The client also exposes `createJob`, `getJob`, `waitForJob`, and `listProfiles`. diff --git a/scripts/release-artifacts.mjs b/scripts/release-artifacts.mjs new file mode 100644 index 0000000..6fc1c88 --- /dev/null +++ b/scripts/release-artifacts.mjs @@ -0,0 +1,35 @@ +import { readFile, writeFile, mkdir, copyFile, readdir } from 'node:fs/promises'; +import { createHash } from 'node:crypto'; +import { createRequire } from 'node:module'; +import { execFileSync } from 'node:child_process'; +import { resolve } from 'node:path'; +const require = createRequire(new URL('../apps/control-plane/package.json', import.meta.url)); +const YAML = require('yaml'); +const version = JSON.parse(await readFile('package.json', 'utf8')).version; +if (!/^\d+\.\d+\.\d+(?:-[a-z0-9.]+)?$/.test(version)) throw new Error('Invalid release version.'); +const directory = resolve(`artifacts/pyro-${version}`); +await mkdir(directory, { recursive: true }); +const compose = YAML.parse(await readFile('docker-compose.yml', 'utf8')); +const digests = process.env.RELEASE_IMAGE_DIGESTS ? JSON.parse(await readFile(process.env.RELEASE_IMAGE_DIGESTS, 'utf8')) : {}; +for (const target of ['gateway', 'control-plane', 'dashboard']) { + delete compose.services[target].build; + const digest = digests[target]; + if (digest && !/^sha256:[a-f0-9]{64}$/.test(digest)) throw new Error('Invalid container digest.'); + compose.services[target].image = `ghcr.io/delvisorlabs/pyro-${target}${digest ? '@' + digest : ':' + version}`; +} +await writeFile(`${directory}/compose.yaml`, YAML.stringify(compose)); +for (const [from, to] of [['.env.example', '.env.example'], ['LICENSE', 'LICENSE'], ['NOTICE', 'NOTICE'], ['THIRD_PARTY_NOTICES.md', 'THIRD_PARTY_NOTICES.md'], ['CHANGELOG.md', 'CHANGELOG.md'], ['docs/deployment.md', 'DEPLOYMENT.md']]) await copyFile(from, `${directory}/${to}`); +await mkdir(`${directory}/profiles`, { recursive: true }); +for (const name of await readdir('profiles')) await copyFile(`profiles/${name}`, `${directory}/profiles/${name}`); +execFileSync('pnpm', ['--filter', '@delvisor/pyro', '--config.ignore-scripts=true', 'pack', '--pack-destination', directory], { stdio: 'inherit' }); +const provenance = { version, commit: execFileSync('git', ['rev-parse', 'HEAD'], { encoding: 'utf8' }).trim(), images: digests, note: Object.keys(digests).length ? 'Container digests are pinned.' : 'Preparation only. Images must be published before this compose file can be used.' }; +await writeFile(`${directory}/release.json`, JSON.stringify(provenance, null, 2) + '\n'); +const entries = await readdir(directory, { recursive: true, withFileTypes: true }); +const sums = []; +for (const entry of entries) if (entry.isFile() && entry.name !== 'SHA256SUMS') { + const path = resolve(entry.parentPath ?? entry.path, entry.name); + const relative = path.slice(directory.length + 1); + sums.push(`${createHash('sha256').update(await readFile(path)).digest('hex')} ${relative}`); +} +await writeFile(`${directory}/SHA256SUMS`, sums.sort().join('\n') + '\n'); +console.log(`Prepared ${directory}`); diff --git a/sdks/python/LICENSE b/sdks/python/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/sdks/python/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/sdks/python/README.md b/sdks/python/README.md index bdfacd4..6a095f7 100644 --- a/sdks/python/README.md +++ b/sdks/python/README.md @@ -17,7 +17,7 @@ decision = pyro.classify({ "messages": [{"role": "user", "content": "Summarize this document."}] }, labels={"session_url": "https://support.example/chats/123", "tenant": "acme"}) -if decision["action"] == "block": +if decision["action"] != "allow": raise RuntimeError(decision["reason"]) ``` diff --git a/sdks/rust/LICENSE b/sdks/rust/LICENSE index a5f8133..d645695 100644 --- a/sdks/rust/LICENSE +++ b/sdks/rust/LICENSE @@ -1,17 +1,202 @@ -Apache License -Version 2.0, January 2004 -http://www.apache.org/licenses/ -Copyright 2026 Pyro contributors + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - http://www.apache.org/licenses/LICENSE-2.0 + 1. Definitions. -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.