From 7b5bdcf4d3bee4e6f398d0226ba8cd3c2754e07a Mon Sep 17 00:00:00 2001 From: master Date: Thu, 30 Oct 2025 00:09:39 +0200 Subject: [PATCH] feat(docs): Add comprehensive documentation for Vexer, Vulnerability Explorer, and Zastava modules - Introduced AGENTS.md, README.md, TASKS.md, and implementation_plan.md for Vexer, detailing mission, responsibilities, key components, and operational notes. - Established similar documentation structure for Vulnerability Explorer and Zastava modules, including their respective workflows, integrations, and observability notes. - Created risk scoring profiles documentation outlining the core workflow, factor model, governance, and deliverables. - Ensured all modules adhere to the Aggregation-Only Contract and maintain determinism and provenance in outputs. --- AGENTS.md | 206 + Mongo2Go-4.1.0/.gitattributes | 1 - .../workflows/continuous-integration.yml | 76 - Mongo2Go-4.1.0/.gitignore | 14 - Mongo2Go-4.1.0/LICENSE | 20 - Mongo2Go-4.1.0/Mongo2Go.sln | 48 - Mongo2Go-4.1.0/README.md | 565 --- Mongo2Go-4.1.0/README_INTERNAL.md | 66 - Mongo2Go-4.1.0/global.json | 8 - Mongo2Go-4.1.0/package_create.sh | 16 - .../src/Mongo2Go/Helper/FileSystem.cs | 44 - .../src/Mongo2Go/Helper/FolderSearch.cs | 112 - .../src/Mongo2Go/Helper/IFileSystem.cs | 10 - .../Mongo2Go/Helper/IMongoBinaryLocator.cs | 7 - .../src/Mongo2Go/Helper/IMongoDbProcess.cs | 11 - .../Mongo2Go/Helper/IMongoDbProcessStarter.cs | 11 - .../src/Mongo2Go/Helper/IPortPool.cs | 10 - .../src/Mongo2Go/Helper/IPortWatcher.cs | 8 - .../src/Mongo2Go/Helper/IProcessWatcher.cs | 7 - .../src/Mongo2Go/Helper/MongoBinaryLocator.cs | 101 - .../Helper/MongoDbProcess.IDisposable.cs | 55 - .../src/Mongo2Go/Helper/MongoDbProcess.cs | 19 - .../Mongo2Go/Helper/MongoDbProcessStarter.cs | 92 - .../src/Mongo2Go/Helper/MongoImportExport.cs | 46 - .../src/Mongo2Go/Helper/MongoLogStatement.cs | 77 - .../src/Mongo2Go/Helper/MongodArguments.cs | 74 - .../Helper/NetStandard21Compatibility.cs | 24 - .../Helper/NoFreePortFoundException.cs | 11 - .../src/Mongo2Go/Helper/PortPool.cs | 37 - .../src/Mongo2Go/Helper/PortWatcher.cs | 38 - .../src/Mongo2Go/Helper/PortWatcherFactory.cs | 14 - .../src/Mongo2Go/Helper/ProcessControl.cs | 163 - .../src/Mongo2Go/Helper/ProcessOutput.cs | 16 - .../src/Mongo2Go/Helper/ProcessWatcher.cs | 13 - .../Mongo2Go/Helper/StringFormatExtension.cs | 27 - .../src/Mongo2Go/Helper/UnixPortWatcher.cs | 46 - .../src/Mongo2Go/Helper/WrappedProcess.cs | 9 - Mongo2Go-4.1.0/src/Mongo2Go/Mongo2Go.csproj | 93 - .../src/Mongo2Go/MongoDbDefaults.cs | 22 - .../MongoDbPortAlreadyTakenException.cs | 11 - .../src/Mongo2Go/MongoDbRunner.IDisposable.cs | 54 - Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.cs | 221 -- .../MonogDbBinariesNotFoundException.cs | 11 - Mongo2Go-4.1.0/src/Mongo2Go/State.cs | 9 - .../src/Mongo2Go/packages.lock.json | 490 --- .../src/Mongo2GoTests/FolderSearchTests.cs | 146 - .../src/Mongo2GoTests/Mongo2GoTests.csproj | 21 - .../MongoDbAdditionalArgumentsTests.cs | 76 - .../Runner/MongoDebuggingTest.cs | 34 - .../Runner/MongoIntegrationTest.cs | 47 - .../Runner/MongoTransactionTest.cs | 36 - .../Runner/RunnerImportExportTests.cs | 89 - .../Runner/RunnerIntegrationTests.cs | 118 - .../src/Mongo2GoTests/Runner/RunnerTests.cs | 108 - .../Runner/RunnerTransactionTests.cs | 190 - .../src/Mongo2GoTests/Runner/TestDocument.cs | 53 - .../src/MongoDownloader/ArchiveExtractor.cs | 152 - .../src/MongoDownloader/ArchiveProgress.cs | 89 - .../src/MongoDownloader/BinaryStripper.cs | 92 - .../src/MongoDownloader/DataModel.cs | 84 - .../src/MongoDownloader/MongoDbDownloader.cs | 162 - .../MongoDownloader/MongoDownloader.csproj | 21 - Mongo2Go-4.1.0/src/MongoDownloader/Options.cs | 100 - Mongo2Go-4.1.0/src/MongoDownloader/Program.cs | 86 - Mongo2Go-4.1.0/src/mongo2go_200_200.png | Bin 21563 -> 0 bytes Mongo2Go-4.1.0/src/mongo2go_big.png | Bin 676725 -> 0 bytes Mongo2Go-4.1.0/tools/README.md | 11 - .../community-server/LICENSE-Community.txt | 557 --- .../community-server/MPL-2 | 373 -- .../community-server/README | 87 - .../community-server/THIRD-PARTY-NOTICES | 1568 -------- .../database-tools/LICENSE.md | 13 - .../database-tools/README.md | 72 - .../database-tools/THIRD-PARTY-NOTICES | 3319 ----------------- .../community-server/LICENSE-Community.txt | 557 --- .../community-server/MPL-2 | 373 -- .../community-server/README | 87 - .../community-server/THIRD-PARTY-NOTICES | 1568 -------- .../database-tools/LICENSE.md | 13 - .../database-tools/README.md | 72 - .../database-tools/THIRD-PARTY-NOTICES | 3319 ----------------- Mongo2Go.4.1.0/.signature.p7s | Bin 12927 -> 0 bytes Mongo2Go.4.1.0/Mongo2Go.nuspec | 46 - Mongo2Go.4.1.0/[Content_Types].xml | 30 - Mongo2Go.4.1.0/_rels/.rels | 5 - Mongo2Go.4.1.0/icon.png | Bin 21563 -> 0 bytes Mongo2Go.4.1.0/lib/net472/Mongo2Go.xml | 175 - .../lib/netstandard2.1/Mongo2Go.xml | 175 - .../002438390f9b42fb9cd0a8f5b12ea55f.psmdcp | 16 - .../community-server/LICENSE-Community.txt | 557 --- .../community-server/MPL-2 | 373 -- .../community-server/README | 87 - .../community-server/THIRD-PARTY-NOTICES | 1568 -------- .../database-tools/LICENSE.md | 13 - .../database-tools/README.md | 72 - .../database-tools/THIRD-PARTY-NOTICES | 3319 ----------------- .../community-server/LICENSE-Community.txt | 557 --- .../community-server/MPL-2 | 373 -- .../community-server/README | 87 - .../community-server/THIRD-PARTY-NOTICES | 1568 -------- .../database-tools/LICENSE.md | 13 - .../database-tools/README.md | 72 - .../database-tools/THIRD-PARTY-NOTICES | 3319 ----------------- .../community-server/LICENSE-Community.txt | 557 --- .../community-server/MPL-2 | 373 -- .../community-server/README | 87 - .../community-server/THIRD-PARTY-NOTICES | 1568 -------- .../database-tools/LICENSE.md | 13 - .../database-tools/README.md | 72 - .../database-tools/THIRD-PARTY-NOTICES | 3319 ----------------- README.md | 5 +- deploy/README.md | 26 +- deploy/telemetry/storage/README.md | 66 +- docs/09_API_CLI_REFERENCE.md | 6 +- docs/10_CONCELIER_CLI_QUICKSTART.md | 2 +- docs/11_DATA_SCHEMAS.md | 16 +- docs/12_PERFORMANCE_WORKBOOK.md | 2 +- docs/13_RELEASE_ENGINEERING_PLAYBOOK.md | 380 +- docs/17_SECURITY_HARDENING_GUIDE.md | 364 +- docs/21_INSTALL_GUIDE.md | 380 +- docs/24_OFFLINE_KIT.md | 98 +- docs/AGENTS.md | 40 +- docs/README.md | 53 +- docs/TASKS.md | 762 ++-- docs/accessibility.md | 262 +- docs/airgap/EPIC_16_AIRGAP_MODE.md | 429 --- docs/airgap/airgap-mode.md | 71 + docs/aoc/aoc-guardrails.md | 26 +- docs/api/EPIC_17_SDKS_OPENAPI.md | 357 -- docs/api/sdk-openapi-program.md | 51 + docs/attestor/EPIC_19_ATTESTOR_CONSOLE.md | 135 - docs/cli-vs-ui-parity.md | 2 +- docs/concelier-connector-research-20251011.md | 2 +- docs/deploy/console.md | 456 +-- docs/deploy/containers.md | 320 +- docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md | 2 +- docs/dev/30_VEXER_CONNECTOR_GUIDE.md | 2 +- .../31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md | 2 +- docs/dev/BUILDX_PLUGIN_QUICKSTART.md | 2 +- docs/dev/authority-dpop-mtls-plan.md | 4 +- docs/dev/fixtures.md | 4 +- docs/dev/merge_semver_playbook.md | 4 +- docs/events/orchestrator-scanner-events.md | 242 +- docs/implplan/AGENTS.md | 112 - docs/implplan/EPIC_1.md | 524 --- docs/implplan/EPIC_10.md | 566 --- docs/implplan/EPIC_11.md | Bin 38590 -> 0 bytes docs/implplan/EPIC_12.md | Bin 40398 -> 0 bytes docs/implplan/EPIC_13.md | Bin 36762 -> 0 bytes docs/implplan/EPIC_14.md | Bin 39386 -> 0 bytes docs/implplan/EPIC_15.md | Bin 37340 -> 0 bytes docs/implplan/EPIC_16.md | 1 - docs/implplan/EPIC_17.md | 1 - docs/implplan/EPIC_18.md | 1 - docs/implplan/EPIC_19.md | 1 - docs/implplan/EPIC_2.md | 567 --- docs/implplan/EPIC_4.md | 409 -- docs/implplan/EPIC_5.md | 431 --- docs/implplan/EPIC_6.md | 650 ---- docs/implplan/EPIC_7.md | 545 --- docs/implplan/EPIC_8.md | 440 --- docs/implplan/EPIC_9.md | 523 --- docs/implplan/EXECPLAN.md | 2 +- docs/implplan/SPRINTS.md | 24 +- docs/implplan/SPRINTS_PRIOR_20251019.md | 16 +- docs/implplan/SPRINTS_PRIOR_20251027.md | 4 +- docs/ingestion/aggregation-only-contract.md | 360 +- docs/moat.md | 430 +++ docs/modules/advisory-ai/AGENTS.md | 22 + docs/modules/advisory-ai/README.md | 29 + docs/modules/advisory-ai/TASKS.md | 9 + docs/modules/advisory-ai/architecture.md | 100 + .../advisory-ai/implementation_plan.md | 19 + docs/modules/attestor/AGENTS.md | 22 + docs/modules/attestor/README.md | 54 + docs/modules/attestor/TASKS.md | 9 + .../attestor/architecture.md} | 43 + docs/modules/attestor/implementation_plan.md | 74 + docs/modules/authority/AGENTS.md | 22 + docs/modules/authority/README.md | 40 + docs/modules/authority/TASKS.md | 9 + .../authority/architecture.md} | 4 +- docs/modules/authority/implementation_plan.md | 22 + .../authority/operations/backup-restore.md} | 0 .../operations/grafana-dashboard.json} | 0 .../authority/operations/key-rotation.md} | 188 +- .../authority/operations/monitoring.md} | 166 +- docs/modules/ci/AGENTS.md | 22 + docs/modules/ci/README.md | 29 + docs/modules/ci/TASKS.md | 9 + docs/modules/ci/architecture.md | 7 + docs/modules/ci/implementation_plan.md | 21 + .../ci/recipes.md} | 510 +-- docs/modules/cli/AGENTS.md | 22 + docs/modules/cli/README.md | 40 + docs/modules/cli/TASKS.md | 9 + .../cli/architecture.md} | 4 +- .../cli/guides}/20_REFERENCE.md | 16 +- .../cli/guides}/cli-reference.md | 632 ++-- docs/{cli => modules/cli/guides}/policy.md | 0 docs/modules/cli/implementation_plan.md | 23 + .../cli/operations/release-and-packaging.md} | 268 +- docs/modules/concelier/AGENTS.md | 22 + docs/modules/concelier/README.md | 36 + docs/modules/concelier/TASKS.md | 9 + .../concelier/architecture.md} | 1118 +++--- docs/modules/concelier/implementation_plan.md | 67 + .../operations/authority-audit-runbook.md} | 318 +- .../operations/conflict-resolution.md} | 0 .../concelier/operations/connectors/apple.md} | 0 .../concelier/operations/connectors/cccs.md} | 0 .../operations/connectors/certbund.md} | 4 +- .../concelier/operations/connectors/cisco.md} | 0 .../cve-kev-grafana-dashboard.json} | 0 .../operations/connectors/cve-kev.md} | 6 +- .../concelier/operations/connectors/ghsa.md} | 0 .../operations/connectors/ics-cisa.md} | 0 .../concelier/operations/connectors/kisa.md} | 0 .../concelier/operations/connectors/msrc.md} | 4 +- .../concelier/operations/connectors/nkcki.md} | 2 +- .../concelier/operations/connectors/osv.md} | 0 .../concelier/operations/mirror.md} | 476 +-- docs/modules/devops/AGENTS.md | 22 + docs/modules/devops/README.md | 41 + docs/modules/devops/TASKS.md | 9 + .../devops/architecture.md} | 10 +- docs/modules/devops/implementation_plan.md | 22 + .../devops/migrations/semver-style.md} | 0 .../devops/runbooks/deployment-upgrade.md} | 302 +- .../devops/runbooks}/launch-cutover.md | 256 +- .../devops/runbooks}/launch-readiness.md | 98 +- .../runbooks}/nuget-preview-bootstrap.md | 0 docs/modules/excititor/AGENTS.md | 22 + docs/modules/excititor/README.md | 33 + docs/modules/excititor/TASKS.md | 9 + .../excititor/architecture.md} | 735 ++-- docs/modules/excititor/implementation_plan.md | 21 + .../excititor/mirrors.md} | 268 +- .../excititor/scoring.md} | 0 docs/modules/export-center/AGENTS.md | 22 + docs/modules/export-center/README.md | 34 + docs/modules/export-center/TASKS.md | 9 + docs/{ => modules}/export-center/api.md | 674 ++-- .../export-center/architecture.md | 252 +- docs/{ => modules}/export-center/cli.md | 462 +-- .../export-center/implementation_plan.md | 66 + .../export-center/mirror-bundles.md | 404 +- .../export-center/operations/runbook.md} | 406 +- docs/{ => modules}/export-center/overview.md | 126 +- docs/{ => modules}/export-center/profiles.md | 278 +- .../export-center/provenance-and-signing.md | 300 +- .../export-center/trivy-adapter.md | 0 docs/modules/graph/AGENTS.md | 22 + docs/modules/graph/README.md | 31 + docs/modules/graph/TASKS.md | 9 + docs/modules/graph/architecture.md | 56 + docs/modules/graph/implementation_plan.md | 64 + docs/modules/notify/AGENTS.md | 22 + docs/modules/notify/README.md | 35 + docs/modules/notify/TASKS.md | 9 + .../notify/architecture.md} | 1026 ++--- docs/modules/notify/implementation_plan.md | 61 + .../samples/notify-channel@1.sample.json | 0 .../notify-delivery-list-response.sample.json | 0 .../samples/notify-event@1.sample.json | 0 .../samples/notify-rule@1.sample.json | 0 .../samples/notify-template@1.sample.json | 0 .../resources}/schemas/notify-channel@1.json | 0 .../resources}/schemas/notify-event@1.json | 0 .../resources}/schemas/notify-rule@1.json | 0 .../resources}/schemas/notify-template@1.json | 0 docs/modules/orchestrator/AGENTS.md | 22 + docs/modules/orchestrator/README.md | 29 + docs/modules/orchestrator/TASKS.md | 9 + docs/modules/orchestrator/architecture.md | 52 + .../orchestrator/implementation_plan.md | 62 + docs/modules/platform/AGENTS.md | 22 + docs/modules/platform/README.md | 29 + docs/modules/platform/TASKS.md | 9 + .../platform/architecture-overview.md} | 336 +- docs/modules/platform/architecture.md | 7 + docs/modules/platform/implementation_plan.md | 22 + docs/modules/policy/AGENTS.md | 22 + docs/modules/policy/README.md | 31 + docs/modules/policy/TASKS.md | 9 + .../policy/architecture.md} | 488 +-- docs/modules/policy/implementation_plan.md | 67 + docs/modules/registry/AGENTS.md | 22 + docs/modules/registry/README.md | 34 + docs/modules/registry/TASKS.md | 9 + docs/modules/registry/architecture.md | 7 + docs/modules/registry/implementation_plan.md | 20 + .../registry/operations/token-service.md} | 0 docs/modules/scanner/AGENTS.md | 22 + docs/modules/scanner/README.md | 38 + docs/modules/scanner/TASKS.md | 9 + .../scanner/architecture.md} | 10 +- docs/modules/scanner/implementation_plan.md | 64 + .../analyzers-grafana-dashboard.json} | 0 .../scanner/operations/analyzers.md} | 4 +- .../operations/entrypoint-dynamic-analysis.md | 72 + .../operations/entrypoint-lang-ccpp.md | 24 + .../operations/entrypoint-lang-deno.md | 22 + .../operations/entrypoint-lang-dotnet.md | 25 + .../operations/entrypoint-lang-elixir.md | 22 + .../scanner/operations/entrypoint-lang-go.md | 24 + .../operations/entrypoint-lang-java.md | 29 + .../operations/entrypoint-lang-nginx.md | 24 + .../operations/entrypoint-lang-node.md | 24 + .../operations/entrypoint-lang-phpfpm.md | 24 + .../operations/entrypoint-lang-python.md | 25 + .../operations/entrypoint-lang-ruby.md | 24 + .../operations/entrypoint-lang-rust.md | 24 + .../operations/entrypoint-lang-supervisor.md | 25 + .../scanner/operations/entrypoint-problem.md | 94 + .../operations/entrypoint-runtime-overview.md | 152 + .../operations/entrypoint-shell-analysis.md | 83 + .../operations/entrypoint-static-analysis.md | 122 + docs/modules/scanner/operations/entrypoint.md | 26 + .../scanner/operations/rustfs-migration.md} | 2 +- docs/modules/scheduler/AGENTS.md | 22 + docs/modules/scheduler/README.md | 37 + docs/modules/scheduler/TASKS.md | 9 + .../scheduler/architecture.md} | 4 +- docs/modules/scheduler/implementation_plan.md | 21 + .../operations/worker-grafana-dashboard.json} | 0 .../operations/worker-prometheus-rules.yaml} | 0 .../scheduler/operations/worker.md} | 6 +- docs/modules/signer/AGENTS.md | 22 + docs/modules/signer/README.md | 30 + docs/modules/signer/TASKS.md | 9 + .../signer/architecture.md} | 2 + docs/modules/signer/implementation_plan.md | 61 + docs/modules/telemetry/AGENTS.md | 22 + docs/modules/telemetry/README.md | 34 + docs/modules/telemetry/TASKS.md | 9 + docs/modules/telemetry/architecture.md | 41 + docs/modules/telemetry/implementation_plan.md | 64 + .../telemetry/operations/collector.md} | 226 +- .../telemetry/operations/storage.md} | 4 +- docs/modules/ui/AGENTS.md | 22 + docs/modules/ui/README.md | 41 + docs/modules/ui/TASKS.md | 9 + .../ui/architecture.md} | 2 + .../ui/console-architecture.md} | 9 +- docs/modules/ui/implementation_plan.md | 25 + .../ui/operations/auth-smoke.md} | 0 docs/modules/vex-lens/AGENTS.md | 22 + docs/modules/vex-lens/README.md | 28 + docs/modules/vex-lens/TASKS.md | 9 + docs/modules/vex-lens/architecture.md | 69 + docs/modules/vex-lens/implementation_plan.md | 63 + docs/modules/vexer/AGENTS.md | 22 + docs/modules/vexer/README.md | 34 + docs/modules/vexer/TASKS.md | 9 + .../vexer/architecture.md} | 4 +- docs/modules/vexer/implementation_plan.md | 65 + .../vexer/scoring.md} | 0 docs/modules/vuln-explorer/AGENTS.md | 22 + docs/modules/vuln-explorer/README.md | 29 + docs/modules/vuln-explorer/TASKS.md | 9 + docs/modules/vuln-explorer/architecture.md | 66 + .../vuln-explorer/implementation_plan.md | 70 + docs/modules/zastava/AGENTS.md | 22 + docs/modules/zastava/README.md | 33 + docs/modules/zastava/TASKS.md | 9 + .../zastava/architecture.md} | 0 docs/modules/zastava/implementation_plan.md | 19 + .../runtime-grafana-dashboard.json} | 0 .../operations/runtime-prometheus-rules.yaml} | 0 .../zastava/operations/runtime.md} | 6 +- docs/notifications/digests.md | 184 +- docs/notifications/overview.md | 152 +- docs/notifications/templates.md | 260 +- docs/observability/observability.md | 8 +- docs/policy/overview.md | 2 +- docs/risk/EPIC_18_RISK_PROFILES.md | 260 -- docs/risk/risk-profiles.md | 57 + docs/security/authority-scopes.md | 522 +-- docs/ui/admin.md | 348 +- docs/ui/console.md | 288 +- docs/ui/findings.md | 358 +- docs/ui/policies.md | 384 +- docs/ui/policy-editor.md | 358 +- docs/ui/runs.md | 338 +- docs/ui/sbom-explorer.md | 390 +- docs/updates/2025-10-22-docs-guild.md | 26 +- .../2025-10-29-export-center-provenance.md | 18 +- node_modules/.package-lock.json | 267 -- ops/deployment/AGENTS.md | 8 +- ops/devops/AGENTS.md | 22 +- ops/devops/README.md | 184 +- ops/devops/TASKS.md | 344 +- .../telemetry/package_offline_bundle.py | 272 +- ops/licensing/AGENTS.md | 8 +- ops/offline-kit/AGENTS.md | 8 +- ops/offline-kit/run-python-analyzer-smoke.sh | 2 +- .../python/StellaOps.Auth.Abstractions.xml | 422 --- .../python/StellaOps.Auth.Client.xml | 233 -- ...ps.Scanner.Analyzers.Lang.Python.deps.json | 858 ----- out/linknotmerge-bench.csv | 4 - out/linknotmerge-bench.json | 84 - out/linknotmerge-bench.prom | 60 - out/linknotmerge-vex-bench.csv | 4 - out/linknotmerge-vex-bench.json | 84 - out/linknotmerge-vex-bench.prom | 50 - out/notify-bench.csv | 4 - out/notify-bench.json | 84 - out/notify-bench.prom | 39 - out/policy-bench.csv | 2 - out/policy-bench.json | 25 - out/policy-bench.prom | 17 - .../policy-simulation-summary.json | 32 - out/tmp-cdx/Program.cs | 4 - out/tmp-cdx/tmp-cdx.csproj | 15 - .../manifest.json | 21 - samples/policy/README.md | 2 +- scripts/export-policy-schemas.sh | 2 +- seed-data/cert-bund/README.md | 6 +- .../StellaOps.Attestor.Types/TASKS.md | 2 +- .../StellaOps.Attestor.Verify/TASKS.md | 2 +- src/Cli/StellaOps.Cli/AGENTS.md | 2 +- src/Cli/StellaOps.Cli/TASKS.md | 4 +- .../TASKS.md | 24 +- .../TASKS.md | 26 +- .../FEEDCONN-CERTCC-02-009_PLAN.md | 2 +- .../TASKS.md | 4 +- .../TASKS.md | 4 +- .../TASKS.md | 2 +- .../TASKS.md | 2 +- .../TASKS.md | 2 +- .../TASKS.md | 22 +- .../TASKS.md | 22 +- .../TASKS.md | 24 +- .../TASKS.md | 22 +- src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md | 143 - .../StellaOps.Excititor.WebService/TASKS.md | 188 +- .../StellaOps.Excititor.Attestation/TASKS.md | 12 +- .../TASKS.md | 14 +- .../TASKS.md | 14 +- .../TASKS.md | 14 +- .../TASKS.md | 14 +- .../TASKS.md | 14 +- .../TASKS.md | 20 +- .../TASKS.md | 14 +- .../TASKS.md | 16 +- .../StellaOps.Excititor.Export/TASKS.md | 16 +- .../StellaOps.Excititor.Formats.CSAF/TASKS.md | 14 +- .../TASKS.md | 14 +- .../TASKS.md | 14 +- .../StellaOps.Excititor.Policy/TASKS.md | 6 +- .../VexPolicyDiagnostics.cs | 174 +- .../VexPolicyDiagnosticsTests.cs | 338 +- .../TASKS.md | 2 +- src/FASTER_MODELING_AND_NORMALIZATION.md | 140 - .../StellaOps.Notify.WebService/AGENTS.md | 8 +- src/Notify/StellaOps.Notify.Worker/AGENTS.md | 8 +- .../AGENTS.md | 8 +- .../AGENTS.md | 8 +- .../AGENTS.md | 8 +- .../AGENTS.md | 8 +- .../StellaOps.Notify.Engine/AGENTS.md | 8 +- .../StellaOps.Notify.Models/AGENTS.md | 8 +- .../StellaOps.Notify.Queue/AGENTS.md | 8 +- .../StellaOps.Notify.Storage.Mongo/AGENTS.md | 8 +- .../StellaOps.Notify.Models.Tests.csproj | 2 +- ...tellaOps.Notify.Storage.Mongo.Tests.csproj | 4 +- .../StellaOps.Notify.WebService.Tests.csproj | 4 +- .../__Libraries/StellaOps.Policy/AGENTS.md | 24 +- .../AGENTS.md | 24 +- .../StellaOps.Scanner.Core/TASKS.md | 14 +- .../StellaOps.Scanner.Queue/AGENTS.md | 30 +- .../StellaOps.Scheduler.WebService/AGENTS.md | 8 +- .../StellaOps.Scheduler.ImpactIndex/AGENTS.md | 8 +- .../StellaOps.Scheduler.Models/AGENTS.md | 8 +- .../StellaOps.Scheduler.Queue/AGENTS.md | 8 +- .../AGENTS.md | 8 +- .../StellaOps.Scheduler.Worker/AGENTS.md | 8 +- .../docs/SCHED-WORKER-16-205-OBSERVABILITY.md | 6 +- .../FixtureUpdater/FixtureUpdater.csproj | 20 + .../Tools}/FixtureUpdater/Program.cs | 756 ++-- .../LanguageAnalyzerSmoke.csproj | 36 +- .../Tools}/LanguageAnalyzerSmoke/Program.cs | 2 +- .../NotifySmokeCheck/NotifySmokeCheck.csproj | 24 +- .../Tools}/NotifySmokeCheck/Program.cs | 396 +- .../PolicyDslValidator.csproj | 28 +- .../Tools}/PolicyDslValidator/Program.cs | 112 +- .../PolicySchemaExporter.csproj | 42 +- .../Tools}/PolicySchemaExporter/Program.cs | 96 +- .../PolicySimulationSmoke.csproj | 28 +- .../Tools}/PolicySimulationSmoke/Program.cs | 582 +-- .../Tools}/RustFsMigrator/Program.cs | 2 +- .../RustFsMigrator/RustFsMigrator.csproj | 0 .../Tools}/SourceStateSeeder/Program.cs | 2 +- .../SourceStateSeeder.csproj | 0 .../Tools}/certbund_offline_snapshot.py | 2 +- .../Tools}/openssl/linux-x64/libcrypto.so.1.1 | Bin .../Tools}/openssl/linux-x64/libssl.so.1.1 | Bin .../IMPLEMENTATION_PLAN.md | 206 +- tmp/docenv/pyvenv.cfg | 5 - tmp/reflect/Program.cs | 13 - tmp/reflect/reflect.csproj | 14 - tools/FixtureUpdater/FixtureUpdater.csproj | 20 - 503 files changed, 16136 insertions(+), 54638 deletions(-) create mode 100644 AGENTS.md delete mode 100644 Mongo2Go-4.1.0/.gitattributes delete mode 100644 Mongo2Go-4.1.0/.github/workflows/continuous-integration.yml delete mode 100644 Mongo2Go-4.1.0/.gitignore delete mode 100644 Mongo2Go-4.1.0/LICENSE delete mode 100644 Mongo2Go-4.1.0/Mongo2Go.sln delete mode 100644 Mongo2Go-4.1.0/README.md delete mode 100644 Mongo2Go-4.1.0/README_INTERNAL.md delete mode 100644 Mongo2Go-4.1.0/global.json delete mode 100644 Mongo2Go-4.1.0/package_create.sh delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/FileSystem.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/FolderSearch.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IFileSystem.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoBinaryLocator.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcess.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcessStarter.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortPool.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortWatcher.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/IProcessWatcher.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoBinaryLocator.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.IDisposable.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcessStarter.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoImportExport.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoLogStatement.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongodArguments.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/NetStandard21Compatibility.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/NoFreePortFoundException.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortPool.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcher.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcherFactory.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessControl.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessOutput.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessWatcher.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/StringFormatExtension.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/UnixPortWatcher.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Helper/WrappedProcess.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/Mongo2Go.csproj delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/MongoDbDefaults.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/MongoDbPortAlreadyTakenException.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.IDisposable.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/MonogDbBinariesNotFoundException.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/State.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2Go/packages.lock.json delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/FolderSearchTests.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Mongo2GoTests.csproj delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/MongoDbAdditionalArgumentsTests.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoDebuggingTest.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoIntegrationTest.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoTransactionTest.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerImportExportTests.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerIntegrationTests.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTests.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTransactionTests.cs delete mode 100644 Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/TestDocument.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/ArchiveExtractor.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/ArchiveProgress.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/BinaryStripper.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/DataModel.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/MongoDbDownloader.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/MongoDownloader.csproj delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/Options.cs delete mode 100644 Mongo2Go-4.1.0/src/MongoDownloader/Program.cs delete mode 100644 Mongo2Go-4.1.0/src/mongo2go_200_200.png delete mode 100644 Mongo2Go-4.1.0/src/mongo2go_big.png delete mode 100644 Mongo2Go-4.1.0/tools/README.md delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/MPL-2 delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/README delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md delete mode 100644 Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go.4.1.0/.signature.p7s delete mode 100644 Mongo2Go.4.1.0/Mongo2Go.nuspec delete mode 100644 Mongo2Go.4.1.0/[Content_Types].xml delete mode 100644 Mongo2Go.4.1.0/_rels/.rels delete mode 100644 Mongo2Go.4.1.0/icon.png delete mode 100644 Mongo2Go.4.1.0/lib/net472/Mongo2Go.xml delete mode 100644 Mongo2Go.4.1.0/lib/netstandard2.1/Mongo2Go.xml delete mode 100644 Mongo2Go.4.1.0/package/services/metadata/core-properties/002438390f9b42fb9cd0a8f5b12ea55f.psmdcp delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/MPL-2 delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/README delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/MPL-2 delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/README delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/README.md delete mode 100644 Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES delete mode 100644 docs/airgap/EPIC_16_AIRGAP_MODE.md create mode 100644 docs/airgap/airgap-mode.md delete mode 100644 docs/api/EPIC_17_SDKS_OPENAPI.md create mode 100644 docs/api/sdk-openapi-program.md delete mode 100644 docs/attestor/EPIC_19_ATTESTOR_CONSOLE.md delete mode 100644 docs/implplan/AGENTS.md delete mode 100644 docs/implplan/EPIC_1.md delete mode 100644 docs/implplan/EPIC_10.md delete mode 100644 docs/implplan/EPIC_11.md delete mode 100644 docs/implplan/EPIC_12.md delete mode 100644 docs/implplan/EPIC_13.md delete mode 100644 docs/implplan/EPIC_14.md delete mode 100644 docs/implplan/EPIC_15.md delete mode 100644 docs/implplan/EPIC_16.md delete mode 100644 docs/implplan/EPIC_17.md delete mode 100644 docs/implplan/EPIC_18.md delete mode 100644 docs/implplan/EPIC_19.md delete mode 100644 docs/implplan/EPIC_2.md delete mode 100644 docs/implplan/EPIC_4.md delete mode 100644 docs/implplan/EPIC_5.md delete mode 100644 docs/implplan/EPIC_6.md delete mode 100644 docs/implplan/EPIC_7.md delete mode 100644 docs/implplan/EPIC_8.md delete mode 100644 docs/implplan/EPIC_9.md create mode 100644 docs/moat.md create mode 100644 docs/modules/advisory-ai/AGENTS.md create mode 100644 docs/modules/advisory-ai/README.md create mode 100644 docs/modules/advisory-ai/TASKS.md create mode 100644 docs/modules/advisory-ai/architecture.md create mode 100644 docs/modules/advisory-ai/implementation_plan.md create mode 100644 docs/modules/attestor/AGENTS.md create mode 100644 docs/modules/attestor/README.md create mode 100644 docs/modules/attestor/TASKS.md rename docs/{ARCHITECTURE_ATTESTOR.md => modules/attestor/architecture.md} (85%) create mode 100644 docs/modules/attestor/implementation_plan.md create mode 100644 docs/modules/authority/AGENTS.md create mode 100644 docs/modules/authority/README.md create mode 100644 docs/modules/authority/TASKS.md rename docs/{ARCHITECTURE_AUTHORITY.md => modules/authority/architecture.md} (96%) create mode 100644 docs/modules/authority/implementation_plan.md rename docs/{ops/authority-backup-restore.md => modules/authority/operations/backup-restore.md} (100%) rename docs/{ops/authority-grafana-dashboard.json => modules/authority/operations/grafana-dashboard.json} (100%) rename docs/{ops/authority-key-rotation.md => modules/authority/operations/key-rotation.md} (96%) rename docs/{ops/authority-monitoring.md => modules/authority/operations/monitoring.md} (97%) create mode 100644 docs/modules/ci/AGENTS.md create mode 100644 docs/modules/ci/README.md create mode 100644 docs/modules/ci/TASKS.md create mode 100644 docs/modules/ci/architecture.md create mode 100644 docs/modules/ci/implementation_plan.md rename docs/{ci/20_CI_RECIPES.md => modules/ci/recipes.md} (97%) create mode 100644 docs/modules/cli/AGENTS.md create mode 100644 docs/modules/cli/README.md create mode 100644 docs/modules/cli/TASKS.md rename docs/{ARCHITECTURE_CLI.md => modules/cli/architecture.md} (96%) rename docs/{cli => modules/cli/guides}/20_REFERENCE.md (78%) rename docs/{cli => modules/cli/guides}/cli-reference.md (93%) rename docs/{cli => modules/cli/guides}/policy.md (100%) create mode 100644 docs/modules/cli/implementation_plan.md rename docs/{operations/cli-release-and-packaging.md => modules/cli/operations/release-and-packaging.md} (94%) create mode 100644 docs/modules/concelier/AGENTS.md create mode 100644 docs/modules/concelier/README.md create mode 100644 docs/modules/concelier/TASKS.md rename docs/{ARCHITECTURE_CONCELIER.md => modules/concelier/architecture.md} (82%) create mode 100644 docs/modules/concelier/implementation_plan.md rename docs/{ops/concelier-authority-audit-runbook.md => modules/concelier/operations/authority-audit-runbook.md} (97%) rename docs/{ops/concelier-conflict-resolution.md => modules/concelier/operations/conflict-resolution.md} (100%) rename docs/{ops/concelier-apple-operations.md => modules/concelier/operations/connectors/apple.md} (100%) rename docs/{ops/concelier-cccs-operations.md => modules/concelier/operations/connectors/cccs.md} (100%) rename docs/{ops/concelier-certbund-operations.md => modules/concelier/operations/connectors/certbund.md} (95%) rename docs/{ops/concelier-cisco-operations.md => modules/concelier/operations/connectors/cisco.md} (100%) rename docs/{ops/concelier-cve-kev-grafana-dashboard.json => modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json} (100%) rename docs/{ops/concelier-cve-kev-operations.md => modules/concelier/operations/connectors/cve-kev.md} (94%) rename docs/{ops/concelier-ghsa-operations.md => modules/concelier/operations/connectors/ghsa.md} (100%) rename docs/{ops/concelier-icscisa-operations.md => modules/concelier/operations/connectors/ics-cisa.md} (100%) rename docs/{ops/concelier-kisa-operations.md => modules/concelier/operations/connectors/kisa.md} (100%) rename docs/{ops/concelier-msrc-operations.md => modules/concelier/operations/connectors/msrc.md} (91%) rename docs/{ops/concelier-nkcki-operations.md => modules/concelier/operations/connectors/nkcki.md} (97%) rename docs/{ops/concelier-osv-operations.md => modules/concelier/operations/connectors/osv.md} (100%) rename docs/{ops/concelier-mirror-operations.md => modules/concelier/operations/mirror.md} (96%) create mode 100644 docs/modules/devops/AGENTS.md create mode 100644 docs/modules/devops/README.md create mode 100644 docs/modules/devops/TASKS.md rename docs/{ARCHITECTURE_DEVOPS.md => modules/devops/architecture.md} (95%) create mode 100644 docs/modules/devops/implementation_plan.md rename docs/{ops/migrations/SEMVER_STYLE.md => modules/devops/migrations/semver-style.md} (100%) rename docs/{ops/deployment-upgrade-runbook.md => modules/devops/runbooks/deployment-upgrade.md} (93%) rename docs/{ops => modules/devops/runbooks}/launch-cutover.md (97%) rename docs/{ops => modules/devops/runbooks}/launch-readiness.md (95%) rename docs/{ops => modules/devops/runbooks}/nuget-preview-bootstrap.md (100%) create mode 100644 docs/modules/excititor/AGENTS.md create mode 100644 docs/modules/excititor/README.md create mode 100644 docs/modules/excititor/TASKS.md rename docs/{ARCHITECTURE_EXCITITOR.md => modules/excititor/architecture.md} (83%) create mode 100644 docs/modules/excititor/implementation_plan.md rename docs/{ARCHITECTURE_EXCITITOR_MIRRORS.md => modules/excititor/mirrors.md} (95%) rename docs/{EXCITITOR_SCORRING.md => modules/excititor/scoring.md} (100%) create mode 100644 docs/modules/export-center/AGENTS.md create mode 100644 docs/modules/export-center/README.md create mode 100644 docs/modules/export-center/TASKS.md rename docs/{ => modules}/export-center/api.md (96%) rename docs/{ => modules}/export-center/architecture.md (97%) rename docs/{ => modules}/export-center/cli.md (96%) create mode 100644 docs/modules/export-center/implementation_plan.md rename docs/{ => modules}/export-center/mirror-bundles.md (95%) rename docs/{operations/export-runbook.md => modules/export-center/operations/runbook.md} (94%) rename docs/{ => modules}/export-center/overview.md (92%) rename docs/{ => modules}/export-center/profiles.md (94%) rename docs/{ => modules}/export-center/provenance-and-signing.md (97%) rename docs/{ => modules}/export-center/trivy-adapter.md (100%) create mode 100644 docs/modules/graph/AGENTS.md create mode 100644 docs/modules/graph/README.md create mode 100644 docs/modules/graph/TASKS.md create mode 100644 docs/modules/graph/architecture.md create mode 100644 docs/modules/graph/implementation_plan.md create mode 100644 docs/modules/notify/AGENTS.md create mode 100644 docs/modules/notify/README.md create mode 100644 docs/modules/notify/TASKS.md rename docs/{ARCHITECTURE_NOTIFY.md => modules/notify/architecture.md} (94%) create mode 100644 docs/modules/notify/implementation_plan.md rename docs/{notify => modules/notify/resources}/samples/notify-channel@1.sample.json (100%) rename docs/{notify => modules/notify/resources}/samples/notify-delivery-list-response.sample.json (100%) rename docs/{notify => modules/notify/resources}/samples/notify-event@1.sample.json (100%) rename docs/{notify => modules/notify/resources}/samples/notify-rule@1.sample.json (100%) rename docs/{notify => modules/notify/resources}/samples/notify-template@1.sample.json (100%) rename docs/{notify => modules/notify/resources}/schemas/notify-channel@1.json (100%) rename docs/{notify => modules/notify/resources}/schemas/notify-event@1.json (100%) rename docs/{notify => modules/notify/resources}/schemas/notify-rule@1.json (100%) rename docs/{notify => modules/notify/resources}/schemas/notify-template@1.json (100%) create mode 100644 docs/modules/orchestrator/AGENTS.md create mode 100644 docs/modules/orchestrator/README.md create mode 100644 docs/modules/orchestrator/TASKS.md create mode 100644 docs/modules/orchestrator/architecture.md create mode 100644 docs/modules/orchestrator/implementation_plan.md create mode 100644 docs/modules/platform/AGENTS.md create mode 100644 docs/modules/platform/README.md create mode 100644 docs/modules/platform/TASKS.md rename docs/{architecture/overview.md => modules/platform/architecture-overview.md} (90%) create mode 100644 docs/modules/platform/architecture.md create mode 100644 docs/modules/platform/implementation_plan.md create mode 100644 docs/modules/policy/AGENTS.md create mode 100644 docs/modules/policy/README.md create mode 100644 docs/modules/policy/TASKS.md rename docs/{architecture/policy-engine.md => modules/policy/architecture.md} (96%) create mode 100644 docs/modules/policy/implementation_plan.md create mode 100644 docs/modules/registry/AGENTS.md create mode 100644 docs/modules/registry/README.md create mode 100644 docs/modules/registry/TASKS.md create mode 100644 docs/modules/registry/architecture.md create mode 100644 docs/modules/registry/implementation_plan.md rename docs/{ops/registry-token-service.md => modules/registry/operations/token-service.md} (100%) create mode 100644 docs/modules/scanner/AGENTS.md create mode 100644 docs/modules/scanner/README.md create mode 100644 docs/modules/scanner/TASKS.md rename docs/{ARCHITECTURE_SCANNER.md => modules/scanner/architecture.md} (97%) create mode 100644 docs/modules/scanner/implementation_plan.md rename docs/{ops/scanner-analyzers-grafana-dashboard.json => modules/scanner/operations/analyzers-grafana-dashboard.json} (100%) rename docs/{ops/scanner-analyzers-operations.md => modules/scanner/operations/analyzers.md} (90%) create mode 100644 docs/modules/scanner/operations/entrypoint-dynamic-analysis.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-ccpp.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-deno.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-dotnet.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-elixir.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-go.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-java.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-nginx.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-node.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-phpfpm.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-python.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-ruby.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-rust.md create mode 100644 docs/modules/scanner/operations/entrypoint-lang-supervisor.md create mode 100644 docs/modules/scanner/operations/entrypoint-problem.md create mode 100644 docs/modules/scanner/operations/entrypoint-runtime-overview.md create mode 100644 docs/modules/scanner/operations/entrypoint-shell-analysis.md create mode 100644 docs/modules/scanner/operations/entrypoint-static-analysis.md create mode 100644 docs/modules/scanner/operations/entrypoint.md rename docs/{ops/scanner-rustfs-migration.md => modules/scanner/operations/rustfs-migration.md} (98%) create mode 100644 docs/modules/scheduler/AGENTS.md create mode 100644 docs/modules/scheduler/README.md create mode 100644 docs/modules/scheduler/TASKS.md rename docs/{ARCHITECTURE_SCHEDULER.md => modules/scheduler/architecture.md} (96%) create mode 100644 docs/modules/scheduler/implementation_plan.md rename docs/{ops/scheduler-worker-grafana-dashboard.json => modules/scheduler/operations/worker-grafana-dashboard.json} (100%) rename docs/{ops/scheduler-worker-prometheus-rules.yaml => modules/scheduler/operations/worker-prometheus-rules.yaml} (100%) rename docs/{ops/scheduler-worker-operations.md => modules/scheduler/operations/worker.md} (91%) create mode 100644 docs/modules/signer/AGENTS.md create mode 100644 docs/modules/signer/README.md create mode 100644 docs/modules/signer/TASKS.md rename docs/{ARCHITECTURE_SIGNER.md => modules/signer/architecture.md} (99%) create mode 100644 docs/modules/signer/implementation_plan.md create mode 100644 docs/modules/telemetry/AGENTS.md create mode 100644 docs/modules/telemetry/README.md create mode 100644 docs/modules/telemetry/TASKS.md create mode 100644 docs/modules/telemetry/architecture.md create mode 100644 docs/modules/telemetry/implementation_plan.md rename docs/{ops/telemetry-collector.md => modules/telemetry/operations/collector.md} (97%) rename docs/{ops/telemetry-storage.md => modules/telemetry/operations/storage.md} (97%) create mode 100644 docs/modules/ui/AGENTS.md create mode 100644 docs/modules/ui/README.md create mode 100644 docs/modules/ui/TASKS.md rename docs/{ARCHITECTURE_UI.md => modules/ui/architecture.md} (98%) rename docs/{architecture/console.md => modules/ui/console-architecture.md} (94%) create mode 100644 docs/modules/ui/implementation_plan.md rename docs/{ops/ui-auth-smoke.md => modules/ui/operations/auth-smoke.md} (100%) create mode 100644 docs/modules/vex-lens/AGENTS.md create mode 100644 docs/modules/vex-lens/README.md create mode 100644 docs/modules/vex-lens/TASKS.md create mode 100644 docs/modules/vex-lens/architecture.md create mode 100644 docs/modules/vex-lens/implementation_plan.md create mode 100644 docs/modules/vexer/AGENTS.md create mode 100644 docs/modules/vexer/README.md create mode 100644 docs/modules/vexer/TASKS.md rename docs/{ARCHITECTURE_VEXER.md => modules/vexer/architecture.md} (97%) create mode 100644 docs/modules/vexer/implementation_plan.md rename docs/{VEXER_SCORRING.md => modules/vexer/scoring.md} (100%) create mode 100644 docs/modules/vuln-explorer/AGENTS.md create mode 100644 docs/modules/vuln-explorer/README.md create mode 100644 docs/modules/vuln-explorer/TASKS.md create mode 100644 docs/modules/vuln-explorer/architecture.md create mode 100644 docs/modules/vuln-explorer/implementation_plan.md create mode 100644 docs/modules/zastava/AGENTS.md create mode 100644 docs/modules/zastava/README.md create mode 100644 docs/modules/zastava/TASKS.md rename docs/{ARCHITECTURE_ZASTAVA.md => modules/zastava/architecture.md} (100%) create mode 100644 docs/modules/zastava/implementation_plan.md rename docs/{ops/zastava-runtime-grafana-dashboard.json => modules/zastava/operations/runtime-grafana-dashboard.json} (100%) rename docs/{ops/zastava-runtime-prometheus-rules.yaml => modules/zastava/operations/runtime-prometheus-rules.yaml} (100%) rename docs/{ops/zastava-runtime-operations.md => modules/zastava/operations/runtime.md} (94%) delete mode 100644 docs/risk/EPIC_18_RISK_PROFILES.md create mode 100644 docs/risk/risk-profiles.md delete mode 100644 node_modules/.package-lock.json delete mode 100644 out/analyzers/python/StellaOps.Auth.Abstractions.xml delete mode 100644 out/analyzers/python/StellaOps.Auth.Client.xml delete mode 100644 out/analyzers/python/StellaOps.Scanner.Analyzers.Lang.Python.deps.json delete mode 100644 out/linknotmerge-bench.csv delete mode 100644 out/linknotmerge-bench.json delete mode 100644 out/linknotmerge-bench.prom delete mode 100644 out/linknotmerge-vex-bench.csv delete mode 100644 out/linknotmerge-vex-bench.json delete mode 100644 out/linknotmerge-vex-bench.prom delete mode 100644 out/notify-bench.csv delete mode 100644 out/notify-bench.json delete mode 100644 out/notify-bench.prom delete mode 100644 out/policy-bench.csv delete mode 100644 out/policy-bench.json delete mode 100644 out/policy-bench.prom delete mode 100644 out/policy-simulations/policy-simulation-summary.json delete mode 100644 out/tmp-cdx/Program.cs delete mode 100644 out/tmp-cdx/tmp-cdx.csproj delete mode 100644 plugins/cli/StellaOps.Cli.Plugins.NonCore/manifest.json delete mode 100644 src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md delete mode 100644 src/FASTER_MODELING_AND_NORMALIZATION.md create mode 100644 src/Tools/FixtureUpdater/FixtureUpdater.csproj rename {tools => src/Tools}/FixtureUpdater/Program.cs (97%) rename {tools => src/Tools}/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj (97%) rename {tools => src/Tools}/LanguageAnalyzerSmoke/Program.cs (99%) rename {tools => src/Tools}/NotifySmokeCheck/NotifySmokeCheck.csproj (97%) rename {tools => src/Tools}/NotifySmokeCheck/Program.cs (97%) rename {tools => src/Tools}/PolicyDslValidator/PolicyDslValidator.csproj (96%) rename {tools => src/Tools}/PolicyDslValidator/Program.cs (96%) rename {tools => src/Tools}/PolicySchemaExporter/PolicySchemaExporter.csproj (81%) rename {tools => src/Tools}/PolicySchemaExporter/Program.cs (94%) rename {tools => src/Tools}/PolicySimulationSmoke/PolicySimulationSmoke.csproj (96%) rename {tools => src/Tools}/PolicySimulationSmoke/Program.cs (97%) rename {tools => src/Tools}/RustFsMigrator/Program.cs (99%) rename {tools => src/Tools}/RustFsMigrator/RustFsMigrator.csproj (100%) rename {tools => src/Tools}/SourceStateSeeder/Program.cs (98%) rename {tools => src/Tools}/SourceStateSeeder/SourceStateSeeder.csproj (100%) rename {tools => src/Tools}/certbund_offline_snapshot.py (99%) rename {tools => src/Tools}/openssl/linux-x64/libcrypto.so.1.1 (100%) rename {tools => src/Tools}/openssl/linux-x64/libssl.so.1.1 (100%) delete mode 100644 tmp/docenv/pyvenv.cfg delete mode 100644 tmp/reflect/Program.cs delete mode 100644 tmp/reflect/reflect.csproj delete mode 100644 tools/FixtureUpdater/FixtureUpdater.csproj diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..01c94915 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,206 @@ +# 1) What is StellaOps? + +**StellaOps** an next-gen and sovereign container-security toolkit built for high-speed, offline operation, released under AGPL-3.0-or-later. + +Stella Ops is a self-hostable, sovereign container-security platform that makes proof—not promises—default. It binds every container digest to content-addressed SBOMs (SBOM 3.0.0 and CycloneDX 1.6), in-toto/DSSE attestations, and optional Sigstore Rekor transparency, then layers deterministic, replayable scanning with entry-trace and VEX-first decisioning. “Next-gen” means findings are reproducible and explainable, exploitability is modeled in OpenVEX and merged with lattice logic for stable outcomes, and the same workflow runs online or fully air-gapped. “Sovereign” means cryptographic and operational independence: bring-your-own trust roots, regional crypto readiness (eIDAS/FIPS/GOST/SM), offline bundles, and post-quantum-ready modes—so regulated orgs can comply without phoning home. + +Our principles and goals are simple: authenticity & integrity by default, provenance attached to digests, transparency for tamper-evidence, determinism & replay for audits, explainability engineers can act on, and exploitability over enumeration to cut noise. We minimize trust and blast radius with short-lived keys, least-privilege, and content-addressed caches; we stay air-gap friendly with mirrored feeds; and we keep governance honest with reviewable OPA/Rego policy gates and VEX-based waivers. The result is a platform that shortens time-to-truth, makes risk measurable, and lets you ship with confidence—anywhere, under any sovereignty requirement. +More documention is available ./docs/*.md files. Read `docs/README.md` to gather information about the available documentation. You could inquiry specific documents as your work requires it + +--- + +# 3) Practices + +## 3.1) Naming +All modules are .NET projects based on .NET 10 (preview). Exclussion is the UI. It is based on Angular +All modules are contained by one or more projects. Each project goes in its dedicated folder. Each project starts with StellaOps.. In case it is common for for all StellaOps modules it is library or plugin and it is named StellaOps.. + +## 3.2) Key technologies & integrations + +- **Runtime**: .NET 10 (`net10.0`) preview SDK; C# latest preview features. Any dependencies like Microsoft.* should strive to be closests version. +- **Nuget**: Try to re-use / cache nugets to /local-nugets +- **Data**: MongoDB (canonical store and job/export state). MongoDB driver version should be > 3.0 +- **Observability**: structured logs, counters, and (optional) OpenTelemetry traces. +- **Ops posture**: offline‑first, allowlist for remote hosts, strict schema validation, gated LLM fallback (only where explicitly configured). + +# 4) Modules +StellaOps ships as containerised building blocks; each module owns a clear boundary and has its own code folder, deployable image, and deep-dive architecture dossier. + +| Module | Primary path(s) | Key doc | +|--------|-----------------|---------| +| Authority | `src/Authority/StellaOps.Authority`
`src/Authority/StellaOps.Authority.Plugin.*` | `docs/modules/authority/architecture.md` | +| Signer | `src/Signer/StellaOps.Signer` | `docs/modules/signer/architecture.md` | +| Attestor | `src/Attestor/StellaOps.Attestor`
`src/Attestor/StellaOps.Attestor.Verify` | `docs/modules/attestor/architecture.md` | +| Concelier | `src/Concelier/StellaOps.Concelier.WebService`
`src/Concelier/__Libraries/StellaOps.Concelier.*` | `docs/modules/concelier/architecture.md` | +| Excititor | `src/Excititor/StellaOps.Excititor.WebService`
`src/Excititor/__Libraries/StellaOps.Excititor.*` | `docs/modules/excititor/architecture.md` | +| Policy Engine | `src/Policy/StellaOps.Policy.Engine`
`src/Policy/__Libraries/StellaOps.Policy.*` | `docs/modules/policy/architecture.md` | +| Scanner | `src/Scanner/StellaOps.Scanner.WebService`
`src/Scanner/StellaOps.Scanner.Worker`
`src/Scanner/__Libraries/StellaOps.Scanner.*` | `docs/modules/scanner/architecture.md` | +| Scheduler | `src/Scheduler/StellaOps.Scheduler.WebService`
`src/Scheduler/StellaOps.Scheduler.Worker` | `docs/modules/scheduler/architecture.md` | +| CLI | `src/Cli/StellaOps.Cli`
`src/Cli/StellaOps.Cli.Core`
`src/Cli/StellaOps.Cli.Plugins.*` | `docs/modules/cli/architecture.md` | +| UI / Console | `src/UI/StellaOps.UI` | `docs/modules/ui/architecture.md` | +| Notify | `src/Notify/StellaOps.Notify.WebService`
`src/Notify/StellaOps.Notify.Worker` | `docs/modules/notify/architecture.md` | +| Export Center | `src/ExportCenter/StellaOps.ExportCenter.WebService`
`src/ExportCenter/StellaOps.ExportCenter.Worker` | `docs/modules/export-center/architecture.md` | +| Registry Token Service | `src/Registry/StellaOps.Registry.TokenService`
`src/Registry/__Tests/StellaOps.Registry.TokenService.Tests` | `docs/modules/registry/architecture.md` | +| Advisory AI | `src/AdvisoryAI/StellaOps.AdvisoryAI` | `docs/modules/advisory-ai/architecture.md` | +| Orchestrator | `src/Orchestrator/StellaOps.Orchestrator` | `docs/modules/orchestrator/architecture.md` | +| Vulnerability Explorer | `src/VulnExplorer/StellaOps.VulnExplorer.Api` | `docs/modules/vuln-explorer/architecture.md` | +| VEX Lens | `src/VexLens/StellaOps.VexLens` | `docs/modules/vex-lens/architecture.md` | +| Graph Explorer | `src/Graph/StellaOps.Graph.Api`
`src/Graph/StellaOps.Graph.Indexer` | `docs/modules/graph/architecture.md` | +| Telemetry Stack | `ops/devops/telemetry` | `docs/modules/telemetry/architecture.md` | +| DevOps / Release | `ops/devops` | `docs/modules/devops/architecture.md` | +| Platform | *(cross-cutting docs)* | `docs/modules/platform/architecture-overview.md` | +| CI Recipes | *(pipeline templates)* | `docs/modules/ci/architecture.md` | +| Zastava | `src/Zastava/StellaOps.Zastava.Observer`
`src/Zastava/StellaOps.Zastava.Webhook`
`src/Zastava/StellaOps.Zastava.Core` | `docs/modules/zastava/architecture.md` | + +## 4.1 Module cheat sheet + +### Authority +- **Path:** `src/Authority/StellaOps.Authority`, plugins in `src/Authority/StellaOps.Authority.Plugin.*`. +- **Docs:** `docs/modules/authority/architecture.md`. +- **Responsibilities:** Issues short-lived, sender-constrained OpToks (DPoP/mTLS) for services, CLI, and UI; exposes OIDC discovery, device-code, and auth-code flows. +- **Key traits:** Ed25519/ES256 signing with JWKS rotation, tenant-aware scopes, stateless JWT validation, optional introspection, and structured audit trails. + +### Signer +- **Path:** `src/Signer/StellaOps.Signer`. +- **Docs:** `docs/modules/signer/architecture.md`. +- **Responsibilities:** Authenticates callers, enforces Proof-of-Entitlement, verifies scanner release signatures, and returns DSSE bundles for SBOMs and reports. +- **Key traits:** Supports keyless (Fulcio) and keyful (KMS/HSM) signing, applies plan quotas, stores audit trails, and delegates Rekor logging to the Attestor. + +### Attestor +- **Path:** `src/Attestor/StellaOps.Attestor`, proof helpers in `src/Attestor/StellaOps.Attestor.Verify`. +- **Docs:** `docs/modules/attestor/architecture.md`. +- **Responsibilities:** Submits DSSE bundles to Rekor v2, caches `{uuid, index, proof}`, and serves verification bundles to Scanner, UI, CLI, and Export Center. +- **Key traits:** mTLS + OpTok enforcement for Signer-only submissions, Mongo/Redis idempotency, optional DSSE archive mirroring, and resilient retry/backoff. + +### Concelier +- **Path:** `src/Concelier/StellaOps.Concelier.WebService` with connectors/exporters under `src/Concelier/__Libraries/StellaOps.Concelier.*`. +- **Docs:** `docs/modules/concelier/architecture.md`. +- **Responsibilities:** Applies the Aggregation-Only Contract to ingest advisories, produce immutable observations, correlate linksets, and publish deterministic exports. +- **Key traits:** Restart-time connectors/exporters, Mongo-backed scheduling, canonical JSON/Trivy outputs, Offline Kit parity, and hash-stable manifests. + +### Excititor +- **Path:** `src/Excititor/StellaOps.Excititor.WebService`, connectors/adapters in `src/Excititor/__Libraries/StellaOps.Excititor.*`. +- **Docs:** `docs/modules/excititor/architecture.md`. +- **Responsibilities:** Normalises VEX statements into observations, builds provenance-rich linksets, and surfaces consensus/conflicts for policy suppression. +- **Key traits:** Aggregation-only guardrails, restart-time plug-ins, Mongo persistence, deterministic exports, and Offline Kit-ready bundles. + +### Policy Engine +- **Path:** `src/Policy/StellaOps.Policy.Engine`, shared libraries under `src/Policy/__Libraries/StellaOps.Policy.*`. +- **Docs:** `docs/modules/policy/architecture.md`. +- **Responsibilities:** Evaluates `stella-dsl@1` policies, joins SBOM/advisory/VEX evidence, materialises effective findings, and emits explain traces. +- **Key traits:** Deterministic evaluation (no wall clock), change-stream driven increments, simulation endpoints, and Authority-scoped tenancy/RBAC enforcement. + +### Scanner.WebService +- **Path:** `src/Scanner/StellaOps.Scanner.WebService`. +- **Docs:** `docs/modules/scanner/architecture.md`. +- **Responsibilities:** Hosts scan/diff/export APIs, enqueues work, serves SBOM and diff artifacts, and publishes DSSE-ready report metadata. +- **Key traits:** Minimal APIs with Redis/NATS queue clients, RustFS artifact integration, BOM-index lookups, and DSSE hand-off to Signer/Attestor. + +### Scanner.Worker +- **Path:** `src/Scanner/StellaOps.Scanner.Worker` with analyzers/caches in `src/Scanner/__Libraries/StellaOps.Scanner.*`. +- **Docs:** `docs/modules/scanner/architecture.md`. +- **Responsibilities:** Runs deterministic OS/language/native analyzers per layer, composes inventory and usage SBOM fragments, and streams them back to the catalog. +- **Key traits:** Layer/file CAS caching, restart-time analyzer plug-ins under `plugins/scanner/**`, bounded retries with lease renewals, and DSSE-ready outputs. + +### Scheduler +- **Path:** `src/Scheduler/StellaOps.Scheduler.WebService`, `src/Scheduler/StellaOps.Scheduler.Worker`. +- **Docs:** `docs/modules/scheduler/architecture.md`. +- **Responsibilities:** Detects advisory/VEX deltas, selects impacted assets via BOM index, and schedules analysis-only runs toward Scanner and Policy Engine. +- **Key traits:** Mongo impact cursors, Redis/NATS orchestration, webhook fan-out (Policy/Notify/Runtime), and deterministic evaluation windows. + +### CLI +- **Path:** `src/Cli/StellaOps.Cli`, helpers in `src/Cli/StellaOps.Cli.Core`, plug-ins in `src/Cli/StellaOps.Cli.Plugins.*`. +- **Docs:** `docs/modules/cli/architecture.md`. +- **Responsibilities:** Provides deterministic verbs for scan/diff/export/report, Buildx SBOM orchestration, policy/VEX administration, and offline kit workflows. +- **Key traits:** Native AOT binaries, device-code/client-credential login with DPoP storage, golden-output tests, and restart-time plug-in manifests in `plugins/cli/**`. + +### UI +- **Path:** `src/UI/StellaOps.UI`. +- **Docs:** `docs/modules/ui/architecture.md`. +- **Responsibilities:** Angular SPA for scans, policy authoring, VEX evidence exploration, runtime posture, and admin tooling via backend APIs. +- **Key traits:** Angular Signals with `@ngrx/signals`, typed API clients handling DPoP + SSE, Tailwind theming, and immutable content-hashed bundles. + +### Notify +- **Path:** `src/Notify/StellaOps.Notify.WebService`, `src/Notify/StellaOps.Notify.Worker`, connectors in `src/Notify/__Libraries`. +- **Docs:** `docs/modules/notify/architecture.md`. +- **Responsibilities:** Evaluates notification rules on platform events, renders channel-specific payloads, and delivers messages with throttling/digests. +- **Key traits:** Tenant-scoped rule engine, idempotent delivery queues, secrets referenced rather than stored, and comprehensive audit/metrics coverage. + +### Export Center +- **Path:** `src/ExportCenter/StellaOps.ExportCenter.WebService`, `src/ExportCenter/StellaOps.ExportCenter.Worker`, adapters in `src/ExportCenter/StellaOps.ExportCenter.*`. +- **Docs:** `docs/modules/export-center/architecture.md`. +- **Responsibilities:** Packages reproducible evidence bundles (JSON, Trivy, mirror) with provenance, signing, and distribution manifests for offline or mirror deployments. +- **Key traits:** Profile-driven exports, Orchestrator-backed job leases, Mongo/object storage staging, and cosign-compatible provenance/signature emission. + +### Registry Token Service +- **Path:** `src/Registry/StellaOps.Registry.TokenService`, with integration tests in `src/Registry/__Tests/StellaOps.Registry.TokenService.Tests`. +- **Docs:** `docs/modules/registry/operations/token-service.md`. +- **Responsibilities:** Issues scoped pull tokens for container/image registries, enforces licence/plan constraints, and publishes audit telemetry for token usage. +- **Key traits:** Authority-issued OpTok validation, Mongo-backed issuance ledger, deterministic checksum manifests for Offline Kit bundles, and emergency revoke/rotation tooling. + +### Zastava +- **Path:** `src/Zastava/StellaOps.Zastava.Observer`, `src/Zastava/StellaOps.Zastava.Webhook`, shared contracts in `src/Zastava/StellaOps.Zastava.Core`. +- **Docs:** `docs/modules/zastava/architecture.md`. +- **Responsibilities:** Observes running workloads, emits runtime posture events, and enforces admission-time policy (signed images, SBOM availability, policy verdict). +- **Key traits:** Authority-issued OpToks with DPoP/mTLS, ND-JSON batching with local buffering, delta-scan triggers on drift, and Kubernetes webhook enforcement. + +--- + +### 4.1.4) Glossary (quick) + +- **OVAL** — Vendor/distro security definition format; authoritative for OS packages. +- **NEVRA / EVR** — RPM and Debian version semantics for OS packages. +- **PURL / SemVer** — Coordinates and version semantics for OSS ecosystems. +- **KEV** — Known Exploited Vulnerabilities (flag only). + +--- +# 5) Your role as StellaOps contributor + +You acting as information technology engineer that will take different type of roles in goal achieving StellaOps production implementation +In order you to work - you have to be supplied with directory that contains `AGENTS.md`,`TASKS.md` files. There will you have more information about the role you have, the scope of your work and the tasks you will have. + +Boundaries: +- You operate only in the working directories I gave you, unless there is dependencies that makes you to work on dependency in shared directory. Then you ask for confirmation. + +You main characteristics: +- Keep endpoints small, deterministic, and cancellation-aware. +- Improve logs/metrics as per tasks. +- Update `TASKS.md` when moving tasks forward. +- When you are done with all task you state explicitly you are done. +- Impersonate the role described on working directory `AGENTS.md` you will read, if role is not available - take role of the CTO of the StellaOps in early stages. +- You always strive for best practices +- You always strive for re-usability +- When in doubt of design decision - you ask then act +- You are autonomus - meaning that you will work for long time alone and achieve maximum without stopping for stupid questions +- You operate on the same directory where other agents will work. In case you need to work on directory that is dependency on provided `AGENTS.md`,`TASKS.md` files you have to ask for confirmation first. + +## 5.1) Type of contributions + +- **BE‑Base (Platform & Pipeline)** + Owns DI, plugin host, job scheduler/coordinator, configuration binding, minimal API endpoints, and Mongo bootstrapping. +- **BE‑Conn‑X (Connectors)** + One agent per source family (NVD, Red Hat, Ubuntu, Debian, SUSE, GHSA, OSV, PSIRTs, CERTs, KEV, ICS). Implements fetch/parse/map with incremental watermarks. +- **BE‑Merge (Canonical Merge & Dedupe)** + Identity graph, precedence policies, canonical JSON serializer, and deterministic hashing (`merge_event`). +- **BE‑Export (JSON & Trivy DB)** + Deterministic export trees, Trivy DB packaging, optional ORAS push, and offline bundle. +- **QA (Validation & Observability)** + Schema tests, fixture goldens, determinism checks, metrics/logs/traces, e2e reproducibility runs. +- **DevEx/Docs** + Maintains this agent framework, templates, and per‑directory guides; assists parallelization and reviews. + + +## 5.2) Work rules (important) + +- **Directory ownership**: Each agent works **only inside its module directory**. Cross‑module edits require a brief handshake in issues/PR description. +- **Scoping**: Use each module’s `AGENTS.md` and `TASKS.md` to plan; autonomous agents must read `src/AGENTS.md` and the module docs before acting. +- **Determinism**: Sort keys, normalize timestamps to UTC ISO‑8601, avoid non‑deterministic data in exports and tests. +- **Status tracking**: Update your module’s `TASKS.md` as you progress (TODO → DOING → DONE/BLOCKED). Before starting of actual work - ensure you have set the task to DOING. When complete or stop update the status in corresponding TASKS.md and in ./SPRINTS.md file. +- **Coordination**: In case task is discovered as blocked on other team or task, according TASKS.md files that dependency is on needs to be changed by adding new tasks describing the requirement. the current task must be updated as completed. In case task changes, scope or requirements or rules - other documentations needs be updated accordingly. +- **Sprint synchronization**: When given task seek for relevant directory to work on from SPRINTS.md. Confirm its state on both SPRINTS.md and the relevant TASKS.md file. Always check the AGENTS.md in the relevant TASKS.md directory. +- **Tests**: Add/extend fixtures and unit tests per change; never regress determinism or precedence. +- **Test layout**: Use module-specific projects in `StellaOps.Concelier..Tests`; shared fixtures/harnesses live in `StellaOps.Concelier.Testing`. +- **Execution autonomous**: In case you need to continue with more than one options just continue sequentially, unless the continue requires design decision. +- **Additional references**: When a task mentions historical epics, consult the corresponding module guides or domain playbooks under `docs/modules/**`, `docs/api/`, `docs/risk/`, or `docs/airgap/` for the latest specification. + +--- diff --git a/Mongo2Go-4.1.0/.gitattributes b/Mongo2Go-4.1.0/.gitattributes deleted file mode 100644 index adea2ff2..00000000 --- a/Mongo2Go-4.1.0/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.nuspec text eol=lf \ No newline at end of file diff --git a/Mongo2Go-4.1.0/.github/workflows/continuous-integration.yml b/Mongo2Go-4.1.0/.github/workflows/continuous-integration.yml deleted file mode 100644 index aaa4d8e4..00000000 --- a/Mongo2Go-4.1.0/.github/workflows/continuous-integration.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Continuous Integration - -on: - push: - branches: - - '**' # Trigger on all branches for commits - tags: - - 'v*' # Trigger only on version tags for deployments - -env: - Configuration: Release - ContinuousIntegrationBuild: true - DOTNET_CLI_TELEMETRY_OPTOUT: true - DOTNET_NOLOGO: true - -jobs: - build: - strategy: - matrix: - os: [macos-latest, ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - name: Build and Test - steps: - - name: Install libssl1.1 (restores libcrypto.so.1.1 which is required by MongoDB binaries v4.4.4) - if: runner.os == 'Linux' - run: | - echo "deb http://security.ubuntu.com/ubuntu focal-security main" | sudo tee /etc/apt/sources.list.d/focal-security.list - sudo apt update - sudo apt install -y libssl1.1 - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Retrieve cached NuGet packages - uses: actions/cache@v4 - with: - path: ~/.nuget/packages - key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }} - - name: Restore NuGet packages - run: dotnet restore --locked-mode --verbosity normal - - name: Build solution - run: dotnet build --configuration ${{ env.Configuration }} --verbosity normal - - name: Run tests - run: dotnet test --configuration ${{ env.Configuration }} --no-build --verbosity normal - - publish: - runs-on: macos-latest - needs: build - if: startsWith(github.ref, 'refs/tags/') - name: Deploy NuGet and GitHub Release - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Restore NuGet packages - run: dotnet restore --locked-mode --verbosity normal - - name: Build solution - run: dotnet build --configuration ${{ env.Configuration }} --verbosity normal - - name: Create NuGet package - run: dotnet pack --output ./artifacts --configuration ${{ env.Configuration }} --verbosity normal - - name: Upload NuGet package artifact - uses: actions/upload-artifact@v4 - with: - name: mongo2go-nuget-package - path: ./artifacts/*.nupkg - - name: Publish NuGet package - run: dotnet nuget push ./artifacts/*.nupkg --source https://api.nuget.org/v3/index.json --api-key "${{ secrets.NUGET_API_KEY }}" --skip-duplicate - - name: Create GitHub Release - run: | - gh release create ${{ github.ref_name }} ./artifacts/*.nupkg \ - --title "${{ github.ref_name }}" \ - --notes "A new release has been created. Please update the release notes manually with details about changes and improvements." \ - --draft - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/.gitignore b/Mongo2Go-4.1.0/.gitignore deleted file mode 100644 index 709ae0f9..00000000 --- a/Mongo2Go-4.1.0/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -src/Mongo2Go/bin/ -src/Mongo2GoTests/bin/ -src/MongoDownloader/bin/ -src/packages/ -obj/ -*ReSharper* -*.suo -*.dotCover -*.user -~$* -*/StyleCop.Cache -*.nupkg -**/.vs -.idea/ diff --git a/Mongo2Go-4.1.0/LICENSE b/Mongo2Go-4.1.0/LICENSE deleted file mode 100644 index 5f8753cb..00000000 --- a/Mongo2Go-4.1.0/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2012-2025 Johannes Hoppe and many ❤️ contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Mongo2Go-4.1.0/Mongo2Go.sln b/Mongo2Go-4.1.0/Mongo2Go.sln deleted file mode 100644 index f6aa5d6c..00000000 --- a/Mongo2Go-4.1.0/Mongo2Go.sln +++ /dev/null @@ -1,48 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2005 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{0B557702-3C09-4514-BDD5-55A44F22113F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mongo2Go", "src\Mongo2Go\Mongo2Go.csproj", "{040A1626-1D04-40D6-BCCF-2D207AE648FC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mongo2GoTests", "src\Mongo2GoTests\Mongo2GoTests.csproj", "{ADE5A672-6A00-4561-BCC1-E5497016DE24}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MongoDownloader", "src\MongoDownloader\MongoDownloader.csproj", "{7E10E0DE-8092-4ECB-B05A-0A15472AB8D2}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{56AB91A3-555C-4D59-BB92-570465DC2CA0}" - ProjectSection(SolutionItems) = preProject - README.md = README.md - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {040A1626-1D04-40D6-BCCF-2D207AE648FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {040A1626-1D04-40D6-BCCF-2D207AE648FC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {040A1626-1D04-40D6-BCCF-2D207AE648FC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {040A1626-1D04-40D6-BCCF-2D207AE648FC}.Release|Any CPU.Build.0 = Release|Any CPU - {ADE5A672-6A00-4561-BCC1-E5497016DE24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ADE5A672-6A00-4561-BCC1-E5497016DE24}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ADE5A672-6A00-4561-BCC1-E5497016DE24}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ADE5A672-6A00-4561-BCC1-E5497016DE24}.Release|Any CPU.Build.0 = Release|Any CPU - {7E10E0DE-8092-4ECB-B05A-0A15472AB8D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7E10E0DE-8092-4ECB-B05A-0A15472AB8D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7E10E0DE-8092-4ECB-B05A-0A15472AB8D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7E10E0DE-8092-4ECB-B05A-0A15472AB8D2}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {040A1626-1D04-40D6-BCCF-2D207AE648FC} = {0B557702-3C09-4514-BDD5-55A44F22113F} - {ADE5A672-6A00-4561-BCC1-E5497016DE24} = {0B557702-3C09-4514-BDD5-55A44F22113F} - {7E10E0DE-8092-4ECB-B05A-0A15472AB8D2} = {0B557702-3C09-4514-BDD5-55A44F22113F} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {08364BFD-1801-4718-83F5-F6F99950B05E} - EndGlobalSection -EndGlobal diff --git a/Mongo2Go-4.1.0/README.md b/Mongo2Go-4.1.0/README.md deleted file mode 100644 index b32b3b31..00000000 --- a/Mongo2Go-4.1.0/README.md +++ /dev/null @@ -1,565 +0,0 @@ -Mongo2Go - MongoDB for integration tests & local debugging -======== - -![Logo](src/mongo2go_200_200.png) - -[![NuGet](https://img.shields.io/nuget/v/Mongo2Go.svg?label=NuGet&logo=NuGet)](https://www.nuget.org/packages/Mongo2Go/) - - -Mongo2Go is a managed wrapper around MongoDB binaries. -It targets **.NET Framework 4.7.2** and **.NET Standard 2.1.** and works with Windows, Linux and macOS. -This Nuget package contains the executables of _mongod_, _mongoimport_ and _mongoexport_ **for Windows, Linux and macOS** . - -__Brought to you by [Johannes Hoppe](https://twitter.com/johanneshoppe) with the help of many ❤️ contributors!__ - -Mongo2Go has two use cases: - -1. Providing multiple, temporary and isolated MongoDB databases for integration tests -2. Providing a quick to set up MongoDB database for a local developer environment - - -Integration test -------------------------------------- -With each call of the static method **MongoDbRunner.Start()** a new MongoDB instance will be set up. -A free port will be used (starting with port 27018) and a corresponding data directory will be created. -The method returns an instance of MongoDbRunner, which implements IDisposable. -As soon as the MongoDbRunner is disposed (or if the Finalizer is called by the GC), -the wrapped MongoDB process will be killed and all data in the data directory will be deleted. - - -Local debugging ------------------------- -In this mode a single MongoDB instance will be started on the default port (27017). -No data will be deleted and the MongoDB instance won’t be killed automatically. -Multiple calls to **MongoDbRunner.StartForDebugging()** will return an instance with the State “AlreadyRunning”. -You can ignore the IDisposable interface, as it won’t have any effect. -**I highly recommend to not use this mode on productive machines!** -Here you should set up a MongoDB as it is described in the manual. -For you convenience the MongoDbRunner also exposes _mongoexport_ and _mongoimport_ -which allow you to quickly set up a working environment. - - -Single server replica set mode to enable transactions -------------------------- -`MongoDbRunner.Start()` can be set up to take in an optional boolean parameter called `singleNodeReplSet`. -When passed in with the value `true` - (**`MongoDbRunner.Start(singleNodeReplSet: true)`**) -- a single node mongod instance will be started as a replica set with the name `singleNodeReplSet`. -Replica set mode is required for transactions to work in MongoDB 4.0 or greater - -Replica set initialization requires the use of a short delay to allow for the replica set to stabilize. This delay is linked to a timeout value of 5 seconds. - -If the timeout expires before the replica set has stabilized a `TimeoutException` will be thrown. - -The default timeout can be changed through the optional parameter `singleNodeReplSetWaitTimeout`, which allows values between 0 and 65535 seconds: **`MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: 10)`** - -Additional mongod arguments ---------------------------- -`MongoDbRunner.Start()` can be set up to consume additional `mongod` arguments. This can be done using the string parameter called `additionalMongodArguments`. - -The list of additional arguments cannot contain arguments already defined internally by Mongo2Go. An `ArgumentException` will be thrown in this case, specifying which additional arguments are required to be discarded. - -Example of usage of the additional `mongod` arguments: **`MongoDbRunner.Start(additionalMongodArguments: "--quiet")`** - -Installation --------------- -The Mongo2Go Nuget package can be found at [https://nuget.org/packages/Mongo2Go/](https://nuget.org/packages/Mongo2Go/) -To install it via the .NET CLI, simply enter: - -```sh -dotnet add package Mongo2Go -``` - -* The new 4.x branch targets __.NET Framework 4.7.2__ and __.NET Standard 2.1__. Please use this version if possible. -* The old 3.x branch targets __.NET Standard 2.0__. No new features will be added, only bugfixes might be made. -* The old 2.x branch targets __.NET Standard 1.6__. No new features will be added, only bugfixes might be made. -* The old 1.x branch targets good-old classic __.NET 4.6.1__. This is for legacy environments only. No changes will be made. - - -Examples --------- - -**Example: Integration Test (here: Machine.Specifications & Fluent Assertions)** - -```c# -[Subject("Runner Integration Test")] -public class when_using_the_inbuild_serialization : MongoIntegrationTest -{ - static TestDocument findResult; - - Establish context = () => - { - CreateConnection(); - _collection.Insert(TestDocument.DummyData1()); - }; - - Because of = () => findResult = _collection.FindOneAs(); - - It should_return_a_result = () => findResult.ShouldNotBeNull(); - It should_hava_expected_data = () => findResult.ShouldHave().AllPropertiesBut(d => d.Id).EqualTo(TestDocument.DummyData1()); - - Cleanup stuff = () => _runner.Dispose(); -} - -public class MongoIntegrationTest -{ - internal static MongoDbRunner _runner; - internal static MongoCollection _collection; - - internal static void CreateConnection() - { - _runner = MongoDbRunner.Start(); - - MongoClient client = new MongoClient(_runner.ConnectionString); - MongoDatabase database = client.GetDatabase("IntegrationTest"); - _collection = database.GetCollection("TestCollection"); - } -} -``` - -More tests can be found at https://github.com/Mongo2Go/Mongo2Go/tree/master/src/Mongo2GoTests/Runner - -**Example: Exporting seed data** - -```c# -using (MongoDbRunner runner = MongoDbRunner.StartForDebugging()) { - - runner.Export("TestDatabase", "TestCollection", @"..\..\App_Data\test.json"); -} -``` - -**Example: Importing for local debugging (compatible with ASP.NET MVC 4 Web API as well as ASP.NET Core)** - -```c# -public class WebApiApplication : System.Web.HttpApplication -{ - private MongoDbRunner _runner; - - protected void Application_Start() - { - _runner = MongoDbRunner.StartForDebugging(); - _runner.Import("TestDatabase", "TestCollection", @"..\..\App_Data\test.json", true); - - MongoClient client = new MongoClient(_runner.ConnectionString); - MongoDatabase database = client.GetDatabase("TestDatabase"); - MongoCollection collection = database.GetCollection("TestCollection"); - - /* happy coding! */ - } - - protected void Application_End() - { - _runner.Dispose(); - } -} -``` - -**Example: Transactions (New feature since v2.2.8)** - -
- Full integration test with transaction handling (click to show) - - -```c# - public class when_transaction_completes : MongoTransactionTest - { - private static TestDocument mainDocument; - private static TestDocument dependentDocument; - Establish context = () => - - { - _runner = MongoDbRunner.Start(singleNodeReplSet: true); - client = new MongoClient(_runner.ConnectionString); - database = client.GetDatabase(_databaseName); - _mainCollection = database.GetCollection(_mainCollectionName); - _dependentCollection = database.GetCollection(_dependentCollectionName); - _mainCollection.InsertOne(TestDocument.DummyData2()); - _dependentCollection.InsertOne(TestDocument.DummyData2()); - }; - - private Because of = () => - { - var filter = Builders.Filter.Where(x => x.IntTest == 23); - var update = Builders.Update.Inc(i => i.IntTest, 10); - - using (var sessionHandle = client.StartSession()) - { - try - { - var i = 0; - while (i < 10) - { - try - { - i++; - sessionHandle.StartTransaction(new TransactionOptions( - readConcern: ReadConcern.Local, - writeConcern: WriteConcern.W1)); - try - { - var first = _mainCollection.UpdateOne(sessionHandle, filter, update); - var second = _dependentCollection.UpdateOne(sessionHandle, filter, update); - } - catch (Exception e) - { - sessionHandle.AbortTransaction(); - throw; - } - - var j = 0; - while (j < 10) - { - try - { - j++; - sessionHandle.CommitTransaction(); - break; - } - catch (MongoException e) - { - if (e.HasErrorLabel("UnknownTransactionCommitResult")) - continue; - throw; - } - } - break; - } - catch (MongoException e) - { - if (e.HasErrorLabel("TransientTransactionError")) - continue; - throw; - } - } - } - catch (Exception e) - { - //failed after multiple attempts so log and do what is appropriate in your case - } - } - - mainDocument = _mainCollection.FindSync(Builders.Filter.Empty).FirstOrDefault(); - dependentDocument = _dependentCollection.FindSync(Builders.Filter.Empty).FirstOrDefault(); - }; - - It main_should_be_33 = () => mainDocument.IntTest.Should().Be(33); - It dependent_should_be_33 = () => dependentDocument.IntTest.Should().Be(33); - Cleanup cleanup = () => _runner.Dispose(); - } - -``` -
- -**Example: Logging with `ILogger`** -
- Wire mongod's logs at info and above levels to a custom `ILogger` (click to show) - -```c# -public class MongoIntegrationTest -{ - internal static MongoDbRunner _runner; - - internal static void CreateConnection() - { - // Create a custom logger. - // Replace this code with your own configuration of an ILogger. - var provider = new ServiceCollection() - .AddLogging(config => - { - // Log to a simple console and to event logs. - config.AddSimpleConsole(); - config.AddEventLog(); - }) - .BuildServiceProvider(); - var logger = provider.GetSerivce().CreateLogger("Mongo2Go"); - - _runner = MongoDbRunner.Start(logger: logger); - } -} -``` -
- -
- Wire mongod's logs at debug levels to a custom `ILogger` (click to show) - -```c# -public class MongoIntegrationTest -{ - internal static MongoDbRunner _runner; - - internal static void CreateConnection() - { - // Create a custom logger. - // Replace this code with your own configuration of an ILogger. - var provider = new ServiceCollection() - .AddLogging(config => - { - // Mongod's D1-D2 levels are logged with Debug level. - // D3-D5 levels are logged with Trace level. - config.SetMinimumLevel(LogLevel.Trace); - - // Log to System.Diagnostics.Debug and to the event source. - config.AddDebug(); - config.AddEventSourceLogger(); - }) - .BuildServiceProvider(); - var logger = provider.GetSerivce().CreateLogger("Mongo2Go"); - - _runner = MongoDbRunner.Start( - additionalMongodArguments: "vvvvv", // Tell mongod to output its D5 level logs - logger: logger); - } -} -``` -
- -Changelog -------------------------------------- - -### Mongo2Go 4.1.0, January 30 2025 - -- Updated **MongoDB.Driver** to version **3.1.0**, ensuring compatibility with the latest MongoDB client features (PR [#156](https://github.com/Mongo2Go/Mongo2Go/pull/156), fixes [#154](https://github.com/Mongo2Go/Mongo2Go/issues/154) - many thanks to [Teneko](https://github.com/teneko)) -- Please note that the bundled version of MongoDB included with this package remains **v4.4.4**. -- **Note for Ubuntu users**: MongoDB 4.4.4 requires **libcrypto.so.1.1**, which is no longer included in Ubuntu 22.04 and newer. If you encounter an error like: - ``` - error while loading shared libraries: libcrypto.so.1.1: cannot open shared object file: No such file or directory - ``` - You can fix this by installing OpenSSL 1.1 manually: - ```bash - echo "deb http://security.ubuntu.com/ubuntu focal-security main" | sudo tee /etc/apt/sources.list.d/focal-security.list - sudo apt update - sudo apt install -y libssl1.1 - ``` - This restores `libcrypto.so.1.1` and allows Mongo2Go/MongoDB to run properly. - - -### Mongo2Go 4.0.0, November 19 2024 - -- A big thank you to [DrewM-Hax0r](https://github.com/DrewM-Hax0r) for championing this release! (PR [#153](https://github.com/Mongo2Go/Mongo2Go/pull/153), fixes [#152](https://github.com/Mongo2Go/Mongo2Go/issues/152)) -- This is a new major version for Mongo2Go (4.x), driven by: - - Dropping support for old .NET Framework versions earlier than 4.7.2 due to updated framework targets. - - MongoDB driver switching to strong-named assemblies (see [.NET Driver Version 2.28.0 Release Notes](https://www.mongodb.com/community/forums/t/net-driver-2-28-0-released/289745)). -- Updated **MongoDB driver to version 3** and re-targeted the project to meet the requirements of the new driver version. -- Fixed an issue with the single-node replica set option, caused by outdated connection strings that were incompatible with the latest MongoDB driver. -- Replaced deprecated dependent packages with updated, supported versions, and patched vulnerabilities by upgrading vulnerable dependencies. -- Please note that the bundled version of MongoDB included with this package has not changed and is still **v4.4.4**. This version of MongoDB is still compatible with the latest version of the driver, so there was no need to update at this time. -- **Bugfix:** Corrected binary search path on Linux when `NUGET_PACKAGES` is specified (PR [#140](https://github.com/Mongo2Go/Mongo2Go/pull/140), fixes [#134](https://github.com/Mongo2Go/Mongo2Go/issues/134) - many thanks to [Ove Andersen](https://github.com/azzlack)) -- **Bugfix**: Stops extra empty temporary data being generated (PR [#138](https://github.com/Mongo2Go/Mongo2Go/pull/138), fixes [#136](https://github.com/Mongo2Go/Mongo2Go/issues/136) - many thanks to [Alex Wardle](https://github.com/awardle)) - -
- Changelog v3.0.0 to 3.1.3 (click to show) - -### Mongo2Go 3.1.3, April 30 2021 - -* targeting .NET Standard 2.0 instead of 2.1, this makes Mongo2Go compatible with .NET Framework (version 4.7.1 and later) (PR [#118](https://github.com/Mongo2Go/Mongo2Go/pull/118) - many thanks to [Cédric Luthi](https://github.com/0xced)) -* fixes handling of the path search for the NUGET_PACKAGE environment variable (PR [#119](https://github.com/Mongo2Go/Mongo2Go/pull/119) - many thanks to [Timm Hoffmeister](https://github.com/vader1986)) -* internal: `dotnet pack` is now used to create the nupkg file for a release (PR [#121](https://github.com/Mongo2Go/Mongo2Go/pull/121) - many thanks to [Cédric Luthi](https://github.com/0xced)) - -### Mongo2Go 3.1.1, April 08 2021 - -* internal: Better algorithm for determining a free port. This allows parallel execution of tests and increases compatibility with Raider and other test runners. (PR [#116](https://github.com/Mongo2Go/Mongo2Go/pull/116), fixes [#115](https://github.com/Mongo2Go/Mongo2Go/issues/115) and [#106](https://github.com/Mongo2Go/Mongo2Go/issues/106) - many thanks to [liangshiwei](https://github.com/realLiangshiwei)) - -### Mongo2Go 3.1.0, April 07 2021 - -* **NEW: Configurable logging!** adds the option to inject a `Microsoft.Extensions.Logging.ILogger` to `MongoDbRunner.Start(logger)` arguments. Now you can adjust or disable the console output to avoid noise in CI environments. Please note the two examples shown above. (PR [#113](https://github.com/Mongo2Go/Mongo2Go/pull/113), fixes [#94](https://github.com/Mongo2Go/Mongo2Go/issues/94), [#95](https://github.com/Mongo2Go/Mongo2Go/issues/95) and [#113](https://github.com/Mongo2Go/Mongo2Go/issues/113) - many thanks to [Corentin Altepe](https://github.com/corentinaltepe)) -* internal: replaces `--sslMode disabled` (deprecated) with `--tlsMode disabled` in command line arguments to mongod. - -### Mongo2Go 3.0.0, March 26 2021 - -* includes MongoDB binaries of **version 4.4.4** with support for Windows, Linux and macOS -* targets **.NET Standard 2.1** (can be used with .NET Core 3.0 and .NET 5.0) - -* adds new MongoDownloader tool (PR [#109](https://github.com/Mongo2Go/Mongo2Go/pull/109), fixes [#82](https://github.com/Mongo2Go/Mongo2Go/issues/82) and [#112](https://github.com/Mongo2Go/Mongo2Go/issues/112) - many thanks to [Cédric Luthi](https://github.com/0xced)) -* adds support for `NUGET_PACKAGES` environment variable (PR [#110](https://github.com/Mongo2Go/Mongo2Go/pull/110) - many thanks to [Bastian Eicher](https://github.com/bastianeicher)) - -
- -
- Changelog v2.0.0-alpha1 to v2.2.16 (click to show) - -### Mongo2Go 2.2.16, December 13 2020 - -* fix for non existing starting path for binary search (PR [#107](https://github.com/Mongo2Go/Mongo2Go/pull/107), fixes [#105](https://github.com/Mongo2Go/Mongo2Go/issues/105) - many thanks to [Gurov Yury](https://github.com/kenoma)) - -### Mongo2Go 2.2.15, December 12 2020 - -* throw exception if cluster is not ready for transactions after `singleNodeReplSetWaitTimeout` (PR [#103](https://github.com/Mongo2Go/Mongo2Go/pull/103) - many thanks for the continued support by [José Mira](https://github.com/zmira)) -s -### Mongo2Go 2.2.14, October 17 2020 - -* fixes a bug with pulling mongo binaries from wrong version (PR [#87](https://github.com/Mongo2Go/Mongo2Go/pull/87), fixes [#86](https://github.com/Mongo2Go/Mongo2Go/issues/86) - many thanks to [mihevc](https://github.com/mihevc)) -* ensures transaction is ready (solves error message: `System.NotSupportedException : StartTransaction cannot determine if transactions are supported because there are no connected servers.`) (PR [#101](https://github.com/Mongo2Go/Mongo2Go/pull/101), fixes [#89](https://github.com/Mongo2Go/Mongo2Go/issues/89), [#91](https://github.com/Mongo2Go/Mongo2Go/issues/91) and [#100](https://github.com/Mongo2Go/Mongo2Go/issues/100) - many thanks to [liangshiwei](https://github.com/realLiangshiwei)) - -### Mongo2Go 2.2.12, September 07 2019 -* performance: waits for replica set ready log message, or throws if timeout expires, instead of using `Thread.Sleep(5000)` (PR [#83](https://github.com/Mongo2Go/Mongo2Go/pull/83), fixes [#80](https://github.com/Mongo2Go/Mongo2Go/issues/80) - many thanks again to [José Mira](https://github.com/zmira)) - -### Mongo2Go 2.2.11, May 10 2019 -* allows additional custom MongoDB arguments (PR [#69](https://github.com/Mongo2Go/Mongo2Go/pull/69), fixes [#68](https://github.com/Mongo2Go/Mongo2Go/issues/68) - many thanks to [José Mira](https://github.com/zmira)) -* adds option to set port for `StartForDebugging()` (PR [#72](https://github.com/Mongo2Go/Mongo2Go/pull/72), fixes [#71](https://github.com/Mongo2Go/Mongo2Go/issues/71) - many thanks to [Danny Bies](https://github.com/dannyBies)) - -### Mongo2Go 2.2.9, February 04 2019 -* fixes a file path issue on Linux if you run on an SDK version beyond .NET Standard 1.6 (PR [#63](https://github.com/Mongo2Go/Mongo2Go/pull/63), fixes [#62](https://github.com/Mongo2Go/Mongo2Go/issues/62) and [#61](https://github.com/Mongo2Go/Mongo2Go/issues/61)) - many thanks to [Jeroen Vannevel](https://github.com/Vannevelj)) -* continuous integration runs on Linux (Travis CI) and Windows (AppVeyor) now - -### Mongo2Go 2.2.8, October 12 2018 -* updated MongoDB binaries to 4.0.2 to support tests leveraging transaction across different collections and databases -* updated MongoDB C# driver to 2.7.0 to be compatible with MongoDB 4.0 -* adds `singleNodeReplSet` paramter to `MongoDbRunner.Start` which allows mongod instance to be started as a replica set to enable transaction support (PR [#57](https://github.com/Mongo2Go/Mongo2Go/pull/57) - many thanks to [Mahi Satyanarayana](https://github.com/gbackmania)) -* fixes port lookup for UnixPortWatcher (PR [#58](https://github.com/Mongo2Go/Mongo2Go/pull/58) - many thanks to [Viktor Kolybaba](https://github.com/VikKol)) - -### Mongo2Go 2.2.7, August 13 2018 -* updates the `MongoBinaryLocator` to look for binaries in the nuget cache if they are not found in the project directory. - * this will make Mongo2Go compatible with projects using the nuget `PackageReference` option. (PR [#56](https://github.com/Mongo2Go/Mongo2Go/pull/56), fixes [#39](https://github.com/Mongo2Go/Mongo2Go/issues/39) and [#55](https://github.com/Mongo2Go/Mongo2Go/issues/55)) -* adds the `binariesSearchDirectory` parameter to `MongoDbRunner.Start` which allows an additional binaries search directory to be provided. - * this will make the db runner more flexible if someone decides to use it in some unpredictable way. -* many thanks to [Nicholas Markkula](https://github.com/nickmkk) - -### Mongo2Go 2.2.6, July 20 2018 -* fixes broken linux support (fixes [#47](https://github.com/Mongo2Go/Mongo2Go/issues/47)) - -### Mongo2Go 2.2.5, July 19 2018 -* fixes unresponsive process issue (PR [#52](https://github.com/Mongo2Go/Mongo2Go/pull/52), fixes [#49](https://github.com/Mongo2Go/Mongo2Go/issues/49)) -* many thanks to [narendrachava](https://github.com/narendrachava) - -### Mongo2Go 2.2.4, June 06 2018 -* better support for TeamCity: removed MaxLevelOfRecursion limitation when searching for MongoDb binaries (PR [#50](https://github.com/Mongo2Go/Mongo2Go/pull/50), fixes [#39](https://github.com/Mongo2Go/Mongo2Go/issues/39)) -* many thanks to [Stanko Culaja](https://github.com/culaja) - -### Mongo2Go 2.2.2, June 05 2018 -* includes mongod, mongoimport and mongoexport v3.6.1 for Windows, Linux and macOS via PR [#46](https://github.com/Mongo2Go/Mongo2Go/pull/46), which fixes [#45](https://github.com/Mongo2Go/Mongo2Go/issues/45) -* many thanks to [Joe Chan](https://github.com/joehmchan) - -### Mongo2Go 2.2.1, November 23 2017 -* no MongoDB binaries changed, still .NET Standard 1.6 -* feature: uses temporary directory instead of good-old windows style `C:\data\db` by default (PR [#42](https://github.com/Mongo2Go/Mongo2Go/pull/42)) - `MongoDbRunner.Start()` and `MongoDbRunner.StartForDebugging()` will now work without any extra parameters for Linux/macOS -* bugfix: runs again on Linux/macOS, by making the binaries executable (PR [#42](https://github.com/Mongo2Go/Mongo2Go/pull/42), which fixes [#37](https://github.com/Mongo2Go/Mongo2Go/issues/37) and might also fix [#43](https://github.com/Mongo2Go/Mongo2Go/issues/43)) -* internal: Unit Tests are running again (PR [#44](https://github.com/Mongo2Go/Mongo2Go/pull/44), which fixes [#31](https://github.com/Mongo2Go/Mongo2Go/issues/31), [#40](https://github.com/Mongo2Go/Mongo2Go/issues/40)) -* internal: No hardcoded path passed to MongoDbRunner constructor (fixes [41](https://github.com/Mongo2Go/Mongo2Go/issues/41)) -* many thanks to [Per Liedman](https://github.com/perliedman) - -### Mongo2Go 2.2.0, August 17 2017 -* includes mongod, mongoimport and mongoexport v3.4.7 for Windows, Linux and macOS -* targets .NET Standard 1.6 (can be used with .NET Core 1.0 / 1.1 / 2.0) -* many thanks to [Aviram Fireberger](https://github.com/avrum) - -### Mongo2Go 2.1.0, March 10 2017 -* skips v2.0 to have same numbers as v1.x. -* no MongoDB binaries changed since 2.0.0-alpha1 (still MongoDB v3.2.7 for Windows, Linux and macOS) -* targets .NET Standard 1.6 (can be used with .NET Core 1.0 / 1.1) -* bugfix: prevent windows firewall popup (PR [#30](https://github.com/Mongo2Go/Mongo2Go/pull/30), which fixes [#21](https://github.com/Mongo2Go/Mongo2Go/pull/21)) -* many thanks to [kubal5003](https://github.com/kubal5003) - -### Mongo2Go 1.1.0, March 10 2017 _(legacy branch!)_ -* no MongoDB binaries changed since v1.0 (still MongoDB v3.2.7 for Windows, Linux and macOS) -* targets .NET 4.6.1 -* bugfix: prevent windows firewall popup (PR [#29](https://github.com/Mongo2Go/Mongo2Go/pull/29), which fixes [#21](https://github.com/Mongo2Go/Mongo2Go/pull/21)) -* many thanks to [kubal5003](https://github.com/kubal5003) - - -### Mongo2Go 2.0.0-alpha1, December 19 2016 -* this version has no support for .NET Framework 4.6, please continue to use the stable package v.1.0.0 -* NEW: first support of .NET Standard 1.6 ([#25](https://github.com/Mongo2Go/Mongo2Go/pull/25)) - * many thanks to [Hassaan Ahmed](https://github.com/bannerflow-hassaan) - * see the [Wiki](https://github.com/Mongo2Go/Mongo2Go/wiki/NetStandard) for more information about .NET Core 1.0 / .NET Standard 1.6 - -
- -
- Changelog v0.1.0 to v1.0.0 (click to show) - -### Mongo2Go 1.0.0, November 14 2016 -* v1.0 finally marked as stable -* no changes to 1.0.0-beta4 -* changes since last stable version (0.2): - * includes mongod, mongoimport and mongoexport v3.2.7 for Windows, Linux and macOS - * support for Windows, Linux and macOS - * uses MongoDB.Driver 2.3.0 - * **requires .NET 4.6** - * various small bugfixes and improvements - -### Mongo2Go 1.0.0-beta4, October 24 2016 -* update to MongoDB.Driver 2.3.0 ([#23](https://github.com/Mongo2Go/Mongo2Go/pull/23)) -* upgraded to __.NET 4.6__ -* internal change: update MSpec as well and add MSTest Adapter for MSpec (ReSharper console runner doesn't support 4.6) -* many thanks to [Alexander Zeitler](https://github.com/AlexZeitler) -* please report any kind of [issues here on github](https://github.com/Mongo2Go/Mongo2Go/issues) so that we can mark 1.0.0 as stable! - -### Mongo2Go 1.0.0-beta3, August 22 2016 -* feature: process windows are hidden now ([#20](https://github.com/Mongo2Go/Mongo2Go/pull/20)) -* bugfix: random folders are used for storing databases ([#18](https://github.com/Mongo2Go/Mongo2Go/pull/18)) -* many thanks to [Matt Kocaj](https://github.com/cottsak) -* please report any kind of [issues here on github](https://github.com/Mongo2Go/Mongo2Go/issues) so that we can mark 1.0.0 as stable! - -### Mongo2Go 1.0.0-beta2, July 29 2016 -* fixes for bugs that were introduced by the big rewrite for cross-platform support -* changes from pull request [#14](https://github.com/Mongo2Go/Mongo2Go/pull/14), which fixes [#12](https://github.com/Mongo2Go/Mongo2Go/issues/12), [#13](https://github.com/Mongo2Go/Mongo2Go/issues/13) and [#15](https://github.com/Mongo2Go/Mongo2Go/issues/15), many thanks to [Mitch Ferrer](https://github.com/G3N7) -* please report any kind of [issues here on github](https://github.com/Mongo2Go/Mongo2Go/issues) so that we can mark 1.0.0 as stable! - - -### Mongo2Go 1.0.0-beta, July 24 2016 -* **:tada: NEW: support for Linux and macOS :tada:** -* many thanks to [Kristofer Linnestjerna](https://github.com/krippz) from [netclean.com](http://www.netclean.com/) for the new cross-platform support -* includes mongod, mongoimport and mongoexport v3.2.7 for Windows, Linux and macOS -* changes from pull request [#8](https://github.com/Mongo2Go/Mongo2Go/pull/8), [#10](https://github.com/Mongo2Go/Mongo2Go/pull/10), [#11](https://github.com/Mongo2Go/Mongo2Go/pull/11) which fixes [#9](https://github.com/Mongo2Go/Mongo2Go/issues/9) -* please report any kind of [issues here on github](https://github.com/Mongo2Go/Mongo2Go/issues) so that we can mark 1.0.0 as stable! - -### Mongo2Go 0.2, May 30 2016 -* includes mongod, mongoimport and mongoexport v3.2.6, - (**64bit** from [win32/mongodb-win32-x86_64-2008plus-3.2.6.zip](http://downloads.mongodb.org/win32/mongodb-win32-x86_64-2008plus-3.2.6.zip?_ga=1.190428203.1815541971.1457905247) since 32bit builds are deprecated now) -* removes outmoded Strong-Name signing from assemblies (please open an issue if you really need this, see also [mspec#190](https://github.com/machine/machine.specifications/issues/190)) -* changes from pull request [#7](https://github.com/Mongo2Go/Mongo2Go/pull/7), thanks to [Mitch Ferrer](https://github.com/G3N7) - -### Mongo2Go 0.1.8, March 13 2016 -* includes mongod, mongoimport and mongoexport v3.0.10 (32bit) -* changes from pull request [#5](https://github.com/Mongo2Go/Mongo2Go/pull/5), thanks to [Aristarkh Zagorodnikov](https://github.com/onyxmaster) - -### Mongo2Go 0.1.6, July 21 2015 -* includes mongod, mongoimport and mongoexport v3.0.4 (32bit) -* bug fix [#4](https://github.com/Mongo2Go/Mongo2Go/issues/4): -Sometimes the runner tries to delete the database directory before the mongod process has been stopped, this throws an IOException. -Now the runner waits until the mongod process has been stopped before the database directory will be deleted. -* Thanks [Sergey Zwezdin](https://github.com/sergun) - -### Mongo2Go 0.1.5, July 08 2015 -* includes mongod, mongoimport and mongoexport v2.6.6 (32bit) -* changes from pull request [#3](https://github.com/Mongo2Go/Mongo2Go/pull/3) -* new: `Start` and `StartForDebugging` methods accept an optional parameter to specify a different data directory (default is "C:\data\db") -* many thanks to [Marc](https://github.com/Silv3rcircl3) - -### Mongo2Go 0.1.4, January 26 2015 -* includes mongod, mongoimport and mongoexport v2.6.6 (32bit) -* changes from pull request [#2](https://github.com/Mongo2Go/Mongo2Go/pull/2) -* internal updates for testing the package (not part of the release) - * updated MSpec package so that it would work with the latest VS and R# test runner - * updated Mongo C# Driver, Fluent Assertions, and Moq packages to latest versions - * fixed date handling for mongoimport and mongoexport to pass tests -* many thanks to [Jesse Sweetland](https://github.com/sweetlandj) - -### Mongo2Go 0.1.3, September 20 2012 -* includes mongod, mongoimport and mongoexport v2.2.0 (32bit) - -### Mongo2Go 0.1.2, August 20 2012 -* stable version -* includes mongod, mongoimport and mongoexport v2.2.0-rc1 (32bit) - -### Mongo2Go 0.1.1, August 16 2012 -* second alpha version -* includes mongod, mongoimport and mongoexport v2.2.0-rc1 (32bit) - - -### Mongo2Go 0.1.0, August 15 2012 -* first alpha version -* includes mongod, mongoimport and mongoexport v2.2.0-rc1 (32bit) - -
- -How to contribute -------------------------------------- - -Just fork the project, make your changes send us a PR. - -In the root folder, just run: -``` -dotnet restore -dotnet build -dotnet test src/Mongo2GoTests -``` diff --git a/Mongo2Go-4.1.0/README_INTERNAL.md b/Mongo2Go-4.1.0/README_INTERNAL.md deleted file mode 100644 index 4d7681ec..00000000 --- a/Mongo2Go-4.1.0/README_INTERNAL.md +++ /dev/null @@ -1,66 +0,0 @@ -# Mongo2Go - Knowledge for Maintainers - -## Creating a Release - -Mongo2Go uses [MinVer](https://github.com/adamralph/minver) for versioning. -Releases are fully automated via GitHub Actions and triggered by tagging a commit with the desired semantic version number. -This process involves two steps to ensure reliable deployments. - -### Steps to Create a Release - -1. **Push Your Changes** - - Commit and push your changes to the main branch. This will trigger a CI build to validate the changes. - ```bash - git commit -m "Your commit message" - git push - ``` - -2. **Wait for the CI Build** - - Ensure that the GitHub Actions workflow completes successfully. This confirms your changes are valid. - -3. **Tag the Commit** - - Once the CI build passes, create a lightweight tag with the desired version number - - Use an **annotated tag** to ensure the release is properly versioned and auditable (`-a` flag): - ```bash - git tag -a v4.0.0 - ``` - - Push the tag to trigger the deployment workflow: - ```bash - git push --tags - ``` - -4. **Draft Release Created** - - The workflow will: - 1. Create a multi-target NuGet package. - 2. Publish the package to nuget.org. - 3. Create a **draft release** on GitHub with a placeholder note. - -5. **Review and Finalize the Release** - - Visit the [Releases page](https://github.com/Mongo2Go/Mongo2Go/releases). - - Open the draft release, update the release notes with details about the changes (e.g., changelog, features, fixes), and publish the release manually. - - -## Workflow Details - -- **Two-Step Process**: - 1. The first push (commit) triggers a CI build to validate the changes. - 2. The second push (tag) triggers the deployment workflow. - -- **Triggers**: - - Commits are validated for all branches. - - Tags starting with `v` trigger deployment. - -- **Draft Releases**: - - Releases are created as drafts, allowing maintainers to review and add release notes before publishing. - -- **Automation**: - - The workflow automates building, testing, publishing to nuget.org, and creating a draft GitHub release. - - -## Best Practices for Maintainers - -- **Semantic Versioning**: Ensure that tags follow the [semantic versioning](https://semver.org/) format (`vMAJOR.MINOR.PATCH`). -- **Pre-Releases**: Use pre-release tags for non-final versions (e.g., `v4.0.0-rc.1`). -- **Detailed Release Notes**: Always add detailed information to the GitHub release, highlighting major changes, fixes, and improvements. -- **Final Review**: Review the draft release to ensure all details are correct before publishing. - diff --git a/Mongo2Go-4.1.0/global.json b/Mongo2Go-4.1.0/global.json deleted file mode 100644 index d4b092c1..00000000 --- a/Mongo2Go-4.1.0/global.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/global", - "sdk": { - "allowPrerelease": false, - "rollForward": "latestMinor", - "version": "8.0.110" - } -} diff --git a/Mongo2Go-4.1.0/package_create.sh b/Mongo2Go-4.1.0/package_create.sh deleted file mode 100644 index 812d1e1c..00000000 --- a/Mongo2Go-4.1.0/package_create.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# just to be sure -#git clean -fdx - -echo -echo "*** Your dotnet version:" -dotnet --version - -echo -echo "*** Creating package:" -dotnet pack --configuration Release src/Mongo2Go/Mongo2Go.csproj -p:ContinuousIntegrationBuild=true - -echo -echo "*** Package content:" -zipinfo src/Mongo2Go/bin/Release/Mongo2Go.*.nupkg \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/FileSystem.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/FileSystem.cs deleted file mode 100644 index a2985009..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/FileSystem.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Diagnostics; -using System.IO; - -namespace Mongo2Go.Helper -{ - public class FileSystem : IFileSystem - { - public void CreateFolder(string path) - { - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - } - - public void DeleteFolder(string path) - { - if (Directory.Exists(path)) - { - Directory.Delete(path, true); - } - } - - public void DeleteFile(string fullFileName) - { - if (File.Exists(fullFileName)) - { - File.Delete(fullFileName); - } - } - - public void MakeFileExecutable (string path) - { - //when on linux or osx we must set the executeble flag on mongo binarys - var p = Process.Start("chmod", $"+x {path}"); - p.WaitForExit(); - - if (p.ExitCode != 0) - { - throw new IOException($"Could not set executable bit for {path}"); - } - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/FolderSearch.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/FolderSearch.cs deleted file mode 100644 index 6ea417b1..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/FolderSearch.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; - -namespace Mongo2Go.Helper -{ - public static class FolderSearch - { - private static readonly char[] _separators = { Path.DirectorySeparatorChar }; - - public static string CurrentExecutingDirectory() - { - string filePath = new Uri(typeof(FolderSearch).GetTypeInfo().Assembly.CodeBase).LocalPath; - return Path.GetDirectoryName(filePath); - } - - public static string FindFolder(this string startPath, string searchPattern) - { - if (startPath == null || searchPattern == null) - { - return null; - } - - string currentPath = startPath; - - foreach (var part in searchPattern.Split(_separators, StringSplitOptions.None)) - { - if (!Directory.Exists(currentPath)) - { - return null; - } - - string[] matchesDirectory = Directory.GetDirectories(currentPath, part); - if (!matchesDirectory.Any()) - { - return null; - } - - if (matchesDirectory.Length > 1) - { - currentPath = MatchVersionToAssemblyVersion(matchesDirectory) - ?? matchesDirectory.OrderBy(x => x).Last(); - } - else - { - currentPath = matchesDirectory.First(); - } - } - - return currentPath; - } - - public static string FindFolderUpwards(this string startPath, string searchPattern) - { - if (string.IsNullOrEmpty(startPath)) - { - return null; - } - - string matchingFolder = startPath.FindFolder(searchPattern); - return matchingFolder ?? startPath.RemoveLastPart().FindFolderUpwards(searchPattern); - } - - internal static string RemoveLastPart(this string path) - { - if (!path.Contains(Path.DirectorySeparatorChar)) - { - return null; - } - - List parts = path.Split(new[] { Path.DirectorySeparatorChar }, StringSplitOptions.None).ToList(); - parts.RemoveAt(parts.Count() - 1); - return string.Join(Path.DirectorySeparatorChar.ToString(), parts.ToArray()); - } - - /// - /// Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - /// - public static string FinalizePath(string fileName) - { - string finalPath; - - if (Path.IsPathRooted(fileName)) - { - finalPath = fileName; - } - else - { - finalPath = Path.Combine(CurrentExecutingDirectory(), fileName); - finalPath = Path.GetFullPath(finalPath); - } - - return finalPath; - } - - private static string MatchVersionToAssemblyVersion(string[] folders) - { - var version = typeof(FolderSearch).GetTypeInfo().Assembly.GetCustomAttribute().InformationalVersion; - - foreach (var folder in folders) - { - var lastFolder = new DirectoryInfo(folder).Name; - if (lastFolder == version) - return folder; - } - - return null; - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IFileSystem.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IFileSystem.cs deleted file mode 100644 index bb827a88..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IFileSystem.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Mongo2Go.Helper -{ - public interface IFileSystem - { - void CreateFolder(string path); - void DeleteFolder(string path); - void DeleteFile(string fullFileName); - void MakeFileExecutable (string path ); - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoBinaryLocator.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoBinaryLocator.cs deleted file mode 100644 index 8efde0ee..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoBinaryLocator.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Mongo2Go.Helper -{ - public interface IMongoBinaryLocator - { - string Directory { get; } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcess.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcess.cs deleted file mode 100644 index 901aa74c..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcess.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Mongo2Go.Helper -{ - public interface IMongoDbProcess : IDisposable - { - IEnumerable StandardOutput { get; } - IEnumerable ErrorOutput { get; } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcessStarter.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcessStarter.cs deleted file mode 100644 index 8fe9c3d3..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IMongoDbProcessStarter.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace Mongo2Go.Helper -{ - public interface IMongoDbProcessStarter - { - IMongoDbProcess Start(string binariesDirectory, string dataDirectory, int port, bool singleNodeReplSet, string additionalMongodArguments, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout, ILogger logger = null); - - IMongoDbProcess Start(string binariesDirectory, string dataDirectory, int port, bool doNotKill, bool singleNodeReplSet, string additionalMongodArguments, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout, ILogger logger = null); - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortPool.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortPool.cs deleted file mode 100644 index 13d1bc5b..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortPool.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Mongo2Go.Helper -{ - public interface IPortPool - { - /// - /// Returns and reserves a new port - /// - int GetNextOpenPort(); - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortWatcher.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortWatcher.cs deleted file mode 100644 index 8a5e0404..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IPortWatcher.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Mongo2Go.Helper -{ - public interface IPortWatcher - { - int FindOpenPort(); - bool IsPortAvailable(int portNumber); - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IProcessWatcher.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IProcessWatcher.cs deleted file mode 100644 index 98045ec3..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/IProcessWatcher.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Mongo2Go.Helper -{ - public interface IProcessWatcher - { - bool IsProcessRunning(string processName); - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoBinaryLocator.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoBinaryLocator.cs deleted file mode 100644 index 96322ba0..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoBinaryLocator.cs +++ /dev/null @@ -1,101 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; - -namespace Mongo2Go.Helper -{ - - public class MongoBinaryLocator : IMongoBinaryLocator - { - private readonly string _nugetPrefix = Path.Combine("packages", "Mongo2Go*"); - private readonly string _nugetCachePrefix = Path.Combine("packages", "mongo2go", "*"); - private readonly string _nugetCacheBasePrefix = Path.Combine("mongo2go", "*"); - public const string DefaultWindowsSearchPattern = @"tools\mongodb-windows*\bin"; - public const string DefaultLinuxSearchPattern = "tools/mongodb-linux*/bin"; - public const string DefaultOsxSearchPattern = "tools/mongodb-macos*/bin"; - public const string WindowsNugetCacheLocation = @"%USERPROFILE%\.nuget\packages"; - public static readonly string OsxAndLinuxNugetCacheLocation = Environment.GetEnvironmentVariable("HOME") + "/.nuget/packages"; - private string _binFolder = string.Empty; - private readonly string _searchPattern; - private readonly string _nugetCacheDirectory; - private readonly string _additionalSearchDirectory; - - public MongoBinaryLocator(string searchPatternOverride, string additionalSearchDirectory) - { - _additionalSearchDirectory = additionalSearchDirectory; - _nugetCacheDirectory = Environment.GetEnvironmentVariable("NUGET_PACKAGES"); - - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - _searchPattern = DefaultOsxSearchPattern; - _nugetCacheDirectory = _nugetCacheDirectory ?? OsxAndLinuxNugetCacheLocation; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - _searchPattern = DefaultLinuxSearchPattern; - _nugetCacheDirectory = _nugetCacheDirectory ?? OsxAndLinuxNugetCacheLocation; - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - _searchPattern = DefaultWindowsSearchPattern; - _nugetCacheDirectory = _nugetCacheDirectory ?? Environment.ExpandEnvironmentVariables(WindowsNugetCacheLocation); - } - else - { - throw new MonogDbBinariesNotFoundException($"Unknown OS: {RuntimeInformation.OSDescription}"); - } - - if (!string.IsNullOrEmpty(searchPatternOverride)) - { - _searchPattern = searchPatternOverride; - } - } - - public string Directory { - get { - if (string.IsNullOrEmpty(_binFolder)){ - return _binFolder = ResolveBinariesDirectory (); - } else { - return _binFolder; - } - } - } - - private string ResolveBinariesDirectory() - { - var searchDirectories = new[] - { - // First search from the additional search directory, if provided - _additionalSearchDirectory, - // Then search from the project directory - FolderSearch.CurrentExecutingDirectory(), - // Finally search from the nuget cache directory - _nugetCacheDirectory - }; - return FindBinariesDirectory(searchDirectories.Where(x => !string.IsNullOrWhiteSpace(x)).ToList()); - } - - private string FindBinariesDirectory(IList searchDirectories) - { - foreach (var directory in searchDirectories) - { - var binaryFolder = - // First try just the search pattern - directory.FindFolderUpwards(_searchPattern) ?? - // Next try the search pattern with nuget installation prefix - directory.FindFolderUpwards(Path.Combine(_nugetPrefix, _searchPattern)) ?? - // Finally try the search pattern with the nuget cache prefix - directory.FindFolderUpwards(Path.Combine(_nugetCachePrefix, _searchPattern)) ?? - // Finally try the search pattern with the basic nuget cache prefix - directory.FindFolderUpwards(Path.Combine(_nugetCacheBasePrefix, _searchPattern)); - if (binaryFolder != null) return binaryFolder; - } - throw new MonogDbBinariesNotFoundException( - $"Could not find Mongo binaries using the search patterns \"{_searchPattern}\", \"{Path.Combine(_nugetPrefix, _searchPattern)}\", \"{Path.Combine(_nugetCachePrefix, _searchPattern)}\", and \"{Path.Combine(_nugetCacheBasePrefix, _searchPattern)}\". " + - $"You can override the search pattern and directory when calling MongoDbRunner.Start. We have detected the OS as {RuntimeInformation.OSDescription}.\n" + - $"We walked up to root directory from the following locations.\n {string.Join("\n", searchDirectories)}"); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.IDisposable.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.IDisposable.cs deleted file mode 100644 index f8443bc8..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.IDisposable.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; - -namespace Mongo2Go.Helper -{ - // IDisposable and friends - public partial class MongoDbProcess - { - ~MongoDbProcess() - { - Dispose(false); - } - - public bool Disposed { get; private set; } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) - { - if (Disposed) - { - return; - } - - if (disposing) - { - // we have no "managed resources" - but we leave this switch to avoid an FxCop CA1801 warnig - } - - if (_process == null) - { - return; - } - - if (_process.DoNotKill) - { - return; - } - - if (!_process.HasExited) - { - _process.Kill(); - _process.WaitForExit(); - } - - _process.Dispose(); - _process = null; - - Disposed = true; - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.cs deleted file mode 100644 index 68affad2..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcess.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Collections.Generic; - -namespace Mongo2Go.Helper -{ - public partial class MongoDbProcess : IMongoDbProcess - { - - private WrappedProcess _process; - - public IEnumerable ErrorOutput { get; set; } - public IEnumerable StandardOutput { get; set; } - - internal MongoDbProcess(WrappedProcess process) - { - _process = process; - } - - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcessStarter.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcessStarter.cs deleted file mode 100644 index 275d346f..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoDbProcessStarter.cs +++ /dev/null @@ -1,92 +0,0 @@ -using Microsoft.Extensions.Logging; -using MongoDB.Bson; -using MongoDB.Driver; -using MongoDB.Driver.Core.Servers; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; - -namespace Mongo2Go.Helper -{ - public class MongoDbProcessStarter : IMongoDbProcessStarter - { - private const string ProcessReadyIdentifier = "waiting for connections"; - private const string Space = " "; - private const string ReplicaSetName = "singleNodeReplSet"; - private const string ReplicaSetReadyIdentifier = "transition to primary complete; database writes are now permitted"; - - /// - /// Starts a new process. Process can be killed - /// - public IMongoDbProcess Start(string binariesDirectory, string dataDirectory, int port, bool singleNodeReplSet, string additionalMongodArguments, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout, ILogger logger = null) - { - return Start(binariesDirectory, dataDirectory, port, false, singleNodeReplSet, additionalMongodArguments, singleNodeReplSetWaitTimeout, logger); - } - - /// - /// Starts a new process. - /// - public IMongoDbProcess Start(string binariesDirectory, string dataDirectory, int port, bool doNotKill, bool singleNodeReplSet, string additionalMongodArguments, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout, ILogger logger = null) - { - string fileName = @"{0}{1}{2}".Formatted(binariesDirectory, System.IO.Path.DirectorySeparatorChar.ToString(), MongoDbDefaults.MongodExecutable); - - string arguments = (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) ? - @"--dbpath ""{0}"" --port {1} --bind_ip 127.0.0.1".Formatted(dataDirectory, port) : - @"--tlsMode disabled --dbpath ""{0}"" --port {1} --bind_ip 127.0.0.1".Formatted(dataDirectory, port); - - arguments = singleNodeReplSet ? arguments + Space + "--replSet" + Space + ReplicaSetName : arguments; - arguments += MongodArguments.GetValidAdditionalArguments(arguments, additionalMongodArguments); - - WrappedProcess wrappedProcess = ProcessControl.ProcessFactory(fileName, arguments); - wrappedProcess.DoNotKill = doNotKill; - - ProcessOutput output = ProcessControl.StartAndWaitForReady(wrappedProcess, 5, ProcessReadyIdentifier, logger); - if (singleNodeReplSet) - { - var replicaSetReady = false; - - // subscribe to output from mongod process and check for replica set ready message - wrappedProcess.OutputDataReceived += (_, args) => replicaSetReady |= !string.IsNullOrWhiteSpace(args.Data) && args.Data.IndexOf(ReplicaSetReadyIdentifier, StringComparison.OrdinalIgnoreCase) >= 0; - - MongoClient client = new MongoClient("mongodb://127.0.0.1:{0}/?directConnection=true&replicaSet={1}".Formatted(port, ReplicaSetName)); - var admin = client.GetDatabase("admin"); - var replConfig = new BsonDocument(new List() - { - new BsonElement("_id", ReplicaSetName), - new BsonElement("members", - new BsonArray {new BsonDocument {{"_id", 0}, {"host", "127.0.0.1:{0}".Formatted(port)}}}) - }); - var command = new BsonDocument("replSetInitiate", replConfig); - admin.RunCommand(command); - - // wait until replica set is ready or until the timeout is reached - SpinWait.SpinUntil(() => replicaSetReady, TimeSpan.FromSeconds(singleNodeReplSetWaitTimeout)); - - if (!replicaSetReady) - { - throw new TimeoutException($"Replica set initialization took longer than the specified timeout of {singleNodeReplSetWaitTimeout} seconds. Please consider increasing the value of {nameof(singleNodeReplSetWaitTimeout)}."); - } - - // wait until transaction is ready or until the timeout is reached - SpinWait.SpinUntil(() => - client.Cluster.Description.Servers.Any(s => s.State == ServerState.Connected && s.IsDataBearing), - TimeSpan.FromSeconds(singleNodeReplSetWaitTimeout)); - - if (!client.Cluster.Description.Servers.Any(s => s.State == ServerState.Connected && s.IsDataBearing)) - { - throw new TimeoutException($"Cluster readiness for transactions took longer than the specified timeout of {singleNodeReplSetWaitTimeout} seconds. Please consider increasing the value of {nameof(singleNodeReplSetWaitTimeout)}."); - } - } - - MongoDbProcess mongoDbProcess = new MongoDbProcess(wrappedProcess) - { - ErrorOutput = output.ErrorOutput, - StandardOutput = output.StandardOutput - }; - - return mongoDbProcess; - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoImportExport.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoImportExport.cs deleted file mode 100644 index c17dc20a..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoImportExport.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Diagnostics; -using System.IO; - -namespace Mongo2Go.Helper -{ - public static class MongoImportExport - { - /// - /// Input File: Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - /// - public static ProcessOutput Import(string binariesDirectory, int port, string database, string collection, string inputFile, bool drop, string additionalMongodArguments = null) - { - string finalPath = FolderSearch.FinalizePath(inputFile); - - if (!File.Exists(finalPath)) - { - throw new FileNotFoundException("File not found", finalPath); - } - - string fileName = Path.Combine("{0}", "{1}").Formatted(binariesDirectory, MongoDbDefaults.MongoImportExecutable); - string arguments = @"--host localhost --port {0} --db {1} --collection {2} --file ""{3}""".Formatted(port, database, collection, finalPath); - if (drop) { arguments += " --drop"; } - arguments += MongodArguments.GetValidAdditionalArguments(arguments, additionalMongodArguments); - - Process process = ProcessControl.ProcessFactory(fileName, arguments); - - return ProcessControl.StartAndWaitForExit(process); - } - - /// - /// Output File: Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - /// - public static ProcessOutput Export(string binariesDirectory, int port, string database, string collection, string outputFile, string additionalMongodArguments = null) - { - string finalPath = FolderSearch.FinalizePath(outputFile); - - string fileName = Path.Combine("{0}", "{1}").Formatted(binariesDirectory, MongoDbDefaults.MongoExportExecutable); - string arguments = @"--host localhost --port {0} --db {1} --collection {2} --out ""{3}""".Formatted(port, database, collection, finalPath); - arguments += MongodArguments.GetValidAdditionalArguments(arguments, additionalMongodArguments); - - Process process = ProcessControl.ProcessFactory(fileName, arguments); - - return ProcessControl.StartAndWaitForExit(process); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoLogStatement.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoLogStatement.cs deleted file mode 100644 index 7abd08d3..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongoLogStatement.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace Mongo2Go.Helper -{ - /// - /// Structure of a log generated by mongod. Used to deserialize the logs - /// and pass them to an ILogger. - /// See: https://docs.mongodb.com/manual/reference/log-messages/#json-log-output-format - /// Note: "truncated" and "size" are not parsed as we're unsure how to - /// properly parse and use them. - /// - class MongoLogStatement - { - [JsonPropertyName("t")] - public MongoDate MongoDate { get; set; } - - /// - /// Severity of the logs as defined by MongoDB. Mapped to LogLevel - /// as defined by Microsoft. - /// D1-D2 mapped to Debug level. D3-D5 mapped Trace level. - /// - [JsonPropertyName("s")] - public string Severity { get; set; } - - public LogLevel Level - { - get - { - if (string.IsNullOrEmpty(Severity)) - return LogLevel.None; - switch (Severity) - { - case "F": return LogLevel.Critical; - case "E": return LogLevel.Error; - case "W": return LogLevel.Warning; - case "I": return LogLevel.Information; - case "D": - case "D1": - case "D2": - return LogLevel.Debug; - case "D3": - case "D4": - case "D5": - default: - return LogLevel.Trace; - } - } - } - - [JsonPropertyName("c")] - public string Component { get; set; } - - [JsonPropertyName("ctx")] - public string Context { get; set; } - - [JsonPropertyName("id")] - public int? Id { get; set; } - - [JsonPropertyName("msg")] - public string Message { get; set; } - - [JsonPropertyName("tags")] - public IEnumerable Tags { get; set; } - - [JsonPropertyName("attr")] - public IDictionary Attributes { get; set; } - } - class MongoDate - { - [JsonPropertyName("$date")] - public DateTime DateTime { get; set; } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongodArguments.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongodArguments.cs deleted file mode 100644 index 3d1edb47..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/MongodArguments.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Mongo2Go.Helper -{ - public static class MongodArguments - { - private const string ArgumentSeparator = "--"; - private const string Space = " "; - - /// - /// Returns the if it is verified that it does not contain any mongod argument already defined by Mongo2Go. - /// - /// mongod arguments defined by Mongo2Go - /// Additional mongod arguments - /// contains at least one mongod argument already defined by Mongo2Go - /// A string with the additional mongod arguments - public static string GetValidAdditionalArguments(string existingMongodArguments, string additionalMongodArguments) - { - if (string.IsNullOrWhiteSpace(additionalMongodArguments)) - { - return string.Empty; - } - - var existingMongodArgumentArray = existingMongodArguments.Trim().Split(new[] { ArgumentSeparator }, StringSplitOptions.RemoveEmptyEntries); - - var existingMongodArgumentOptions = new List(); - for (var i = 0; i < existingMongodArgumentArray.Length; i++) - { - var argumentOptionSplit = existingMongodArgumentArray[i].Split(' '); - - if (argumentOptionSplit.Length == 0 - || string.IsNullOrWhiteSpace(argumentOptionSplit[0].Trim())) - { - continue; - } - - existingMongodArgumentOptions.Add(argumentOptionSplit[0].Trim()); - } - - var additionalMongodArgumentArray = additionalMongodArguments.Trim().Split(new[] { ArgumentSeparator }, StringSplitOptions.RemoveEmptyEntries); - - var validAdditionalMongodArguments = new List(); - var duplicateMongodArguments = new List(); - for (var i = 0; i < additionalMongodArgumentArray.Length; i++) - { - var additionalArgument = additionalMongodArgumentArray[i].Trim(); - var argumentOptionSplit = additionalArgument.Split(' '); - - if (argumentOptionSplit.Length == 0 - || string.IsNullOrWhiteSpace(argumentOptionSplit[0].Trim())) - { - continue; - } - - if (existingMongodArgumentOptions.Contains(argumentOptionSplit[0].Trim())) - { - duplicateMongodArguments.Add(argumentOptionSplit[0].Trim()); - } - - validAdditionalMongodArguments.Add(ArgumentSeparator + additionalArgument); - } - - if (duplicateMongodArguments.Count != 0) - { - throw new ArgumentException($"mongod arguments defined by Mongo2Go ({string.Join(", ", existingMongodArgumentOptions)}) cannot be overriden. Please remove the following additional argument(s): {string.Join(", ", duplicateMongodArguments)}."); - } - - return validAdditionalMongodArguments.Count == 0 - ? string.Empty - : Space + string.Join(" ", validAdditionalMongodArguments); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/NetStandard21Compatibility.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/NetStandard21Compatibility.cs deleted file mode 100644 index 31e6fbbf..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/NetStandard21Compatibility.cs +++ /dev/null @@ -1,24 +0,0 @@ -#if NETSTANDARD2_0 -using System; - -namespace Mongo2Go.Helper -{ - public static class NetStandard21Compatibility - { - /// - /// Returns a value indicating whether a specified string occurs within this , using the specified comparison rules. - /// - /// The string to operate on. - /// The string to seek. - /// One of the enumeration values that specifies the rules to use in the comparison. - /// if the parameter occurs within this string, or if is the empty string (""); otherwise, . - /// is - public static bool Contains(this string @string, string value, StringComparison comparisonType) - { - if (@string == null) throw new ArgumentNullException(nameof(@string)); - - return @string.IndexOf(value, comparisonType) >= 0; - } - } -} -#endif diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/NoFreePortFoundException.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/NoFreePortFoundException.cs deleted file mode 100644 index 04443d6a..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/NoFreePortFoundException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Mongo2Go.Helper -{ - public class NoFreePortFoundException : Exception - { - public NoFreePortFoundException() { } - public NoFreePortFoundException(string message) : base(message) { } - public NoFreePortFoundException(string message, Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortPool.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortPool.cs deleted file mode 100644 index 1b26a47b..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortPool.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; - -namespace Mongo2Go.Helper -{ - /// - /// Intention: port numbers won't be assigned twice to avoid connection problems with integration tests - /// - public sealed class PortPool : IPortPool - { - private static readonly PortPool Instance = new PortPool(); - - // Explicit static constructor to tell C# compiler - // not to mark type as beforefieldinit - static PortPool() - { - } - - // Singleton - private PortPool() - { - } - - public static PortPool GetInstance - { - get { return Instance; } - } - - /// - /// Returns and reserves a new port - /// - public int GetNextOpenPort() - { - IPortWatcher portWatcher = PortWatcherFactory.CreatePortWatcher(); - return portWatcher.FindOpenPort(); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcher.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcher.cs deleted file mode 100644 index 3dccdf8d..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcher.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.Linq; -using System.Net; -using System.Net.NetworkInformation; -using System.Net.Sockets; - -namespace Mongo2Go.Helper -{ - public class PortWatcher : IPortWatcher - { - public int FindOpenPort() - { - // Locate a free port on the local machine by binding a socket to - // an IPEndPoint using IPAddress.Any and port 0. The socket will - // select a free port. - int listeningPort = 0; - Socket portSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - try - { - IPEndPoint socketEndPoint = new IPEndPoint(IPAddress.Any, 0); - portSocket.Bind(socketEndPoint); - socketEndPoint = (IPEndPoint)portSocket.LocalEndPoint; - listeningPort = socketEndPoint.Port; - } - finally - { - portSocket.Close(); - } - - return listeningPort; - } - - public bool IsPortAvailable(int portNumber) - { - IPEndPoint[] tcpConnInfoArray = IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners(); - return tcpConnInfoArray.All(endpoint => endpoint.Port != portNumber); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcherFactory.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcherFactory.cs deleted file mode 100644 index 18ab1821..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/PortWatcherFactory.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Mongo2Go.Helper -{ - public class PortWatcherFactory - { - public static IPortWatcher CreatePortWatcher() - { - return RuntimeInformation.IsOSPlatform(OSPlatform.Linux) - ? (IPortWatcher) new UnixPortWatcher() - : new PortWatcher(); - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessControl.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessControl.cs deleted file mode 100644 index 72a455f7..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessControl.cs +++ /dev/null @@ -1,163 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Text.Json; -using System.Threading; - -namespace Mongo2Go.Helper -{ - public static class ProcessControl - { - public static WrappedProcess ProcessFactory(string fileName, string arguments) - { - ProcessStartInfo startInfo = new ProcessStartInfo - { - FileName = fileName, - Arguments = arguments, - CreateNoWindow = true, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true - }; - - WrappedProcess process = new WrappedProcess { StartInfo = startInfo }; - return process; - } - - public static ProcessOutput StartAndWaitForExit(Process process) - { - List errorOutput = new List(); - List standardOutput = new List(); - - process.ErrorDataReceived += (sender, args) => errorOutput.Add(args.Data); - process.OutputDataReceived += (sender, args) => standardOutput.Add(args.Data); - - process.Start(); - - process.BeginErrorReadLine(); - process.BeginOutputReadLine(); - - process.WaitForExit(); - - process.CancelErrorRead(); - process.CancelOutputRead(); - - return new ProcessOutput(errorOutput, standardOutput); - } - - /// - /// Reads from Output stream to determine if process is ready - /// - public static ProcessOutput StartAndWaitForReady(Process process, int timeoutInSeconds, string processReadyIdentifier, ILogger logger = null) - { - if (timeoutInSeconds < 1 || - timeoutInSeconds > 10) - { - throw new ArgumentOutOfRangeException("timeoutInSeconds", "The amount in seconds should have a value between 1 and 10."); - } - - // Determine when the process is ready, and store the error and standard outputs - // to eventually return them. - List errorOutput = new List(); - List standardOutput = new List(); - bool processReady = false; - - void OnProcessOnErrorDataReceived(object sender, DataReceivedEventArgs args) => errorOutput.Add(args.Data); - void OnProcessOnOutputDataReceived(object sender, DataReceivedEventArgs args) - { - standardOutput.Add(args.Data); - - if (!string.IsNullOrEmpty(args.Data) && args.Data.IndexOf(processReadyIdentifier, StringComparison.OrdinalIgnoreCase) >= 0) - { - processReady = true; - } - } - - process.ErrorDataReceived += OnProcessOnErrorDataReceived; - process.OutputDataReceived += OnProcessOnOutputDataReceived; - - if (logger == null) - WireLogsToConsoleAndDebugOutput(process); - else - WireLogsToLogger(process, logger); - - process.Start(); - - process.BeginErrorReadLine(); - process.BeginOutputReadLine(); - - int lastResortCounter = 0; - int timeOut = timeoutInSeconds * 10; - while (!processReady) - { - Thread.Sleep(100); - if (++lastResortCounter > timeOut) - { - // we waited X seconds. - // for any reason the detection did not worked, eg. the identifier changed - // lets assume everything is still ok - break; - } - } - - //unsubscribing writing to list - to prevent memory overflow. - process.ErrorDataReceived -= OnProcessOnErrorDataReceived; - process.OutputDataReceived -= OnProcessOnOutputDataReceived; - - return new ProcessOutput(errorOutput, standardOutput); - } - - /// - /// Send the mongod process logs to .NET's console and debug outputs. - /// - /// - private static void WireLogsToConsoleAndDebugOutput(Process process) - { - void DebugOutputHandler(object sender, DataReceivedEventArgs args) => Debug.WriteLine(args.Data); - void ConsoleOutputHandler(object sender, DataReceivedEventArgs args) => Console.WriteLine(args.Data); - - //Writing to debug trace & console to enable test runners to capture the output - process.ErrorDataReceived += DebugOutputHandler; - process.ErrorDataReceived += ConsoleOutputHandler; - process.OutputDataReceived += DebugOutputHandler; - process.OutputDataReceived += ConsoleOutputHandler; - } - - /// - /// Parses and redirects mongod logs to ILogger. - /// - /// - /// - private static void WireLogsToLogger(Process process, ILogger logger) - { - // Parse the structured log and wire it to logger - void OnReceivingLogFromMongod(object sender, DataReceivedEventArgs args) - { - if (string.IsNullOrWhiteSpace(args.Data)) - return; - try - { - var log = JsonSerializer.Deserialize(args.Data); - logger.Log(log.Level, - "{message} - {attributes} - {date} - {component} - {context} - {id} - {tags}", - log.Message, log.Attributes, log.MongoDate.DateTime, log.Component, log.Context, log.Id, log.Tags); - } - catch (Exception ex) when (ex is JsonException || ex is NotSupportedException) - { - logger.LogWarning(ex, - "Failed parsing the mongod logs {log}. It could be that the format has changed. " + - "See: https://docs.mongodb.com/manual/reference/log-messages/#std-label-log-message-json-output-format", - args.Data); - } - catch (Exception) - { - // Nothing else to do. Swallow the exception and do not wire the logs. - } - }; - process.ErrorDataReceived += OnReceivingLogFromMongod; - process.OutputDataReceived += OnReceivingLogFromMongod; - } - - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessOutput.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessOutput.cs deleted file mode 100644 index 925af15a..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessOutput.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; - -namespace Mongo2Go.Helper -{ - public class ProcessOutput - { - public ProcessOutput(IEnumerable errorOutput, IEnumerable standardOutput) - { - StandardOutput = standardOutput; - ErrorOutput = errorOutput; - } - - public IEnumerable StandardOutput { get; private set; } - public IEnumerable ErrorOutput { get; private set; } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessWatcher.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessWatcher.cs deleted file mode 100644 index 287ad4c9..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/ProcessWatcher.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Diagnostics; -using System.Linq; - -namespace Mongo2Go.Helper -{ - public class ProcessWatcher : IProcessWatcher - { - public bool IsProcessRunning(string processName) - { - return Process.GetProcessesByName(processName).Any(); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/StringFormatExtension.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/StringFormatExtension.cs deleted file mode 100644 index dbe6b5a3..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/StringFormatExtension.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Globalization; - -namespace Mongo2Go.Helper -{ - /// - /// saves about 40 keystrokes - /// - public static class StringFormatExtension - { - /// - /// Populates the template using the provided arguments and the invariant culture - /// - public static string Formatted(this string template, params object[] args) - { - return template.Formatted(CultureInfo.InvariantCulture, args); - } - - /// - /// Populates the template using the provided arguments using the provided formatter - /// - public static string Formatted(this string template, IFormatProvider formatter, params object[] args) - { - return string.IsNullOrEmpty(template) ? string.Empty : string.Format(formatter, template, args); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/UnixPortWatcher.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/UnixPortWatcher.cs deleted file mode 100644 index ffec7894..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/UnixPortWatcher.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Net; -using System.Net.Sockets; - -namespace Mongo2Go.Helper -{ - - public class UnixPortWatcher : IPortWatcher - { - public int FindOpenPort () - { - // Locate a free port on the local machine by binding a socket to - // an IPEndPoint using IPAddress.Any and port 0. The socket will - // select a free port. - int listeningPort = 0; - Socket portSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - try - { - IPEndPoint socketEndPoint = new IPEndPoint(IPAddress.Any, 0); - portSocket.Bind(socketEndPoint); - socketEndPoint = (IPEndPoint)portSocket.LocalEndPoint; - listeningPort = socketEndPoint.Port; - } - finally - { - portSocket.Close(); - } - - return listeningPort; - } - - public bool IsPortAvailable (int portNumber) - { - TcpListener tcpListener = new TcpListener (IPAddress.Loopback, portNumber); - try { - tcpListener.Start (); - return true; - } - catch (SocketException) { - return false; - } finally - { - tcpListener.Stop (); - } - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/WrappedProcess.cs b/Mongo2Go-4.1.0/src/Mongo2Go/Helper/WrappedProcess.cs deleted file mode 100644 index d0093738..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Helper/WrappedProcess.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Diagnostics; - -namespace Mongo2Go.Helper -{ - public class WrappedProcess : Process - { - public bool DoNotKill { get; set; } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/Mongo2Go.csproj b/Mongo2Go-4.1.0/src/Mongo2Go/Mongo2Go.csproj deleted file mode 100644 index 4d2555eb..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/Mongo2Go.csproj +++ /dev/null @@ -1,93 +0,0 @@ - - - - net472;netstandard2.1 - Johannes Hoppe and many contributors - Mongo2Go is a managed wrapper around MongoDB binaries. It targets .NET Framework 4.7.2 and .NET Standard 2.1. -This Nuget package contains the executables of mongod, mongoimport and mongoexport v4.4.4 for Windows, Linux and macOS. - - -Mongo2Go has two use cases: - -1. Providing multiple, temporary and isolated MongoDB databases for integration tests -2. Providing a quick to set up MongoDB database for a local developer environment - HAUS HOPPE - ITS - Copyright © 2012-2025 Johannes Hoppe and many ❤️ contributors - true - icon.png - MIT - https://github.com/Mongo2Go/Mongo2Go - https://github.com/Mongo2Go/Mongo2Go/releases - MongoDB Mongo unit test integration runner - https://github.com/Mongo2Go/Mongo2Go - git - Mongo2Go - Mongo2Go is a managed wrapper around MongoDB binaries. - - - - 4 - 1701;1702;1591;1573 - - - - 4 - 1701;1702;1591;1573 - - - - 1701;1702;1591;1573 - - - - 1701;1702;1591;1573 - - - - true - true - true - - - - embedded - true - true - - - - v - - - - - - true - icon.png - - - true - tools - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbDefaults.cs b/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbDefaults.cs deleted file mode 100644 index ef112211..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbDefaults.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Mongo2Go -{ - public static class MongoDbDefaults - { - public const string ProcessName = "mongod"; - - public const string MongodExecutable = "mongod"; - - public const string MongoExportExecutable = "mongoexport"; - - public const string MongoImportExecutable = "mongoimport"; - - public const int DefaultPort = 27017; - - // but we don't want to get in trouble with productive systems - public const int TestStartPort = 27018; - - public const string Lockfile = "mongod.lock"; - - public const int SingleNodeReplicaSetWaitTimeout = 10; - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbPortAlreadyTakenException.cs b/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbPortAlreadyTakenException.cs deleted file mode 100644 index d272bd84..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbPortAlreadyTakenException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Mongo2Go -{ - public class MongoDbPortAlreadyTakenException : Exception - { - public MongoDbPortAlreadyTakenException() { } - public MongoDbPortAlreadyTakenException(string message) : base(message) { } - public MongoDbPortAlreadyTakenException(string message, Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.IDisposable.cs b/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.IDisposable.cs deleted file mode 100644 index bd894bbe..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.IDisposable.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; - -namespace Mongo2Go -{ - // IDisposable and friends - public partial class MongoDbRunner - { - ~MongoDbRunner() - { - Dispose(false); - } - - public bool Disposed { get; private set; } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) - { - if (Disposed) - { - return; - } - - if (State != State.Running) - { - return; - } - - if (disposing) - { - // we have no "managed resources" - but we leave this switch to avoid an FxCop CA1801 warnig - } - - if (_mongoDbProcess != null) - { - _mongoDbProcess.Dispose(); - } - - // will be null if we are working in debugging mode (single instance) - if (_dataDirectoryWithPort != null) - { - // finally clean up the data directory we created previously - _fileSystem.DeleteFolder(_dataDirectoryWithPort); - } - - Disposed = true; - State = State.Stopped; - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.cs b/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.cs deleted file mode 100644 index 6818c151..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/MongoDbRunner.cs +++ /dev/null @@ -1,221 +0,0 @@ -using Microsoft.Extensions.Logging; -using Mongo2Go.Helper; -using System; -using System.IO; -using System.Runtime.InteropServices; - -namespace Mongo2Go -{ - /// - /// Mongo2Go main entry point - /// - public partial class MongoDbRunner : IDisposable - { - private readonly IMongoDbProcess _mongoDbProcess; - private readonly IFileSystem _fileSystem; - private readonly string _dataDirectoryWithPort; - private readonly int _port; - private readonly IMongoBinaryLocator _mongoBin; - - /// - /// State of the current MongoDB instance - /// - public State State { get; private set; } - - /// - /// Connections string that should be used to establish a connection the MongoDB instance - /// - public string ConnectionString { get; private set; } - - /// - /// Starts Multiple MongoDB instances with each call - /// On dispose: kills them and deletes their data directory - /// - /// (Optional) If null, mongod logs are wired to .NET's Console and Debug output (provided you haven't added the --quiet additional argument). - /// If not null, mongod logs are parsed and wired to the provided logger. - /// Should be used for integration tests - public static MongoDbRunner Start(string dataDirectory = null, string binariesSearchPatternOverride = null, string binariesSearchDirectory = null, bool singleNodeReplSet = false, string additionalMongodArguments = null, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout, ILogger logger = null) - { - if (dataDirectory == null) { - dataDirectory = GetTemporaryDataDirectory(); - } - - // this is required to support multiple instances to run in parallel - dataDirectory += Guid.NewGuid().ToString().Replace("-", "").Substring(0, 20); - - return new MongoDbRunner( - PortPool.GetInstance, - new FileSystem(), - new MongoDbProcessStarter(), - new MongoBinaryLocator(binariesSearchPatternOverride, binariesSearchDirectory), - dataDirectory, - singleNodeReplSet, - additionalMongodArguments, - singleNodeReplSetWaitTimeout, - logger); - } - - /// - /// !!! - /// This method is only used for an internal unit test. Use MongoDbRunner.Start() instead. - /// But if you find it to be useful (eg. to change every aspect on your own) feel free to implement the interfaces on your own! - /// - /// see https://github.com/Mongo2Go/Mongo2Go/issues/41 - [Obsolete("Use MongoDbRunner.Start() if possible.")] - public static MongoDbRunner StartUnitTest( - IPortPool portPool, - IFileSystem fileSystem, - IMongoDbProcessStarter processStarter, - IMongoBinaryLocator mongoBin, - string dataDirectory = null, - string additionalMongodArguments = null) - { - return new MongoDbRunner( - portPool, - fileSystem, - processStarter, - mongoBin, - dataDirectory, - additionalMongodArguments: additionalMongodArguments); - } - - /// - /// Only starts one single MongoDB instance (even on multiple calls), does not kill it, does not delete data - /// - /// - /// Should be used for local debugging only - /// WARNING: one single instance on one single machine is not a suitable setup for productive environments!!! - /// - public static MongoDbRunner StartForDebugging(string dataDirectory = null, string binariesSearchPatternOverride = null, string binariesSearchDirectory = null, bool singleNodeReplSet = false, int port = MongoDbDefaults.DefaultPort, string additionalMongodArguments = null, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout) - { - return new MongoDbRunner( - new ProcessWatcher(), - new PortWatcher(), - new FileSystem(), - new MongoDbProcessStarter(), - new MongoBinaryLocator(binariesSearchPatternOverride, binariesSearchDirectory), port, dataDirectory, singleNodeReplSet, additionalMongodArguments, singleNodeReplSetWaitTimeout); - } - - /// - /// !!! - /// This method is only used for an internal unit test. Use MongoDbRunner.StartForDebugging() instead. - /// But if you find it to be useful (eg. to change every aspect on your own) feel free to implement the interfaces on your own! - /// - /// see https://github.com/Mongo2Go/Mongo2Go/issues/41 - [Obsolete("Use MongoDbRunner.StartForDebugging() if possible.")] - public static MongoDbRunner StartForDebuggingUnitTest( - IProcessWatcher processWatcher, - IPortWatcher portWatcher, - IFileSystem fileSystem, - IMongoDbProcessStarter processStarter, - IMongoBinaryLocator mongoBin, - string dataDirectory = null, - string additionalMongodArguments = null) - { - return new MongoDbRunner( - processWatcher, - portWatcher, - fileSystem, - processStarter, - mongoBin, - MongoDbDefaults.DefaultPort, - dataDirectory, - additionalMongodArguments: additionalMongodArguments); - } - - /// - /// Executes Mongoimport on the associated MongoDB Instace - /// - public void Import(string database, string collection, string inputFile, bool drop, string additionalMongodArguments = null) - { - MongoImportExport.Import(_mongoBin.Directory, _port, database, collection, inputFile, drop, additionalMongodArguments); - } - - /// - /// Executes Mongoexport on the associated MongoDB Instace - /// - public void Export(string database, string collection, string outputFile, string additionalMongodArguments = null) - { - MongoImportExport.Export(_mongoBin.Directory, _port, database, collection, outputFile, additionalMongodArguments); - } - - /// - /// usage: local debugging - /// - private MongoDbRunner(IProcessWatcher processWatcher, IPortWatcher portWatcher, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin, int port, string dataDirectory = null, bool singleNodeReplSet = false, string additionalMongodArguments = null, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout) - { - _fileSystem = fileSystem; - _mongoBin = mongoBin; - _port = port; - - MakeMongoBinarysExecutable(); - - ConnectionString = singleNodeReplSet - ? "mongodb://127.0.0.1:{0}/?directConnection=true&replicaSet=singleNodeReplSet&readPreference=primary".Formatted(_port) - : "mongodb://127.0.0.1:{0}/".Formatted(_port); - - if (processWatcher.IsProcessRunning(MongoDbDefaults.ProcessName) && !portWatcher.IsPortAvailable(_port)) - { - State = State.AlreadyRunning; - return; - } - - if (!portWatcher.IsPortAvailable(_port)) - { - throw new MongoDbPortAlreadyTakenException("MongoDB can't be started. The TCP port {0} is already taken.".Formatted(_port)); - } - - if (dataDirectory == null) { - dataDirectory = GetTemporaryDataDirectory(); - } - - _fileSystem.CreateFolder(dataDirectory); - _fileSystem.DeleteFile("{0}{1}{2}".Formatted(dataDirectory, Path.DirectorySeparatorChar.ToString(), MongoDbDefaults.Lockfile)); - _mongoDbProcess = processStarter.Start(_mongoBin.Directory, dataDirectory, _port, true, singleNodeReplSet, additionalMongodArguments, singleNodeReplSetWaitTimeout); - - State = State.Running; - } - - /// - /// usage: integration tests - /// - private MongoDbRunner(IPortPool portPool, IFileSystem fileSystem, IMongoDbProcessStarter processStarter, IMongoBinaryLocator mongoBin, string dataDirectory = null, bool singleNodeReplSet = false, string additionalMongodArguments = null, ushort singleNodeReplSetWaitTimeout = MongoDbDefaults.SingleNodeReplicaSetWaitTimeout, ILogger logger = null) - { - _fileSystem = fileSystem; - _port = portPool.GetNextOpenPort(); - _mongoBin = mongoBin; - - if (dataDirectory == null) { - dataDirectory = GetTemporaryDataDirectory(); - } - - MakeMongoBinarysExecutable(); - - ConnectionString = singleNodeReplSet - ? "mongodb://127.0.0.1:{0}/?directConnection=true&replicaSet=singleNodeReplSet&readPreference=primary".Formatted(_port) - : "mongodb://127.0.0.1:{0}/".Formatted(_port); - - _dataDirectoryWithPort = "{0}_{1}".Formatted(dataDirectory, _port); - _fileSystem.CreateFolder(_dataDirectoryWithPort); - _fileSystem.DeleteFile("{0}{1}{2}".Formatted(_dataDirectoryWithPort, Path.DirectorySeparatorChar.ToString(), MongoDbDefaults.Lockfile)); - - _mongoDbProcess = processStarter.Start(_mongoBin.Directory, _dataDirectoryWithPort, _port, singleNodeReplSet, additionalMongodArguments, singleNodeReplSetWaitTimeout, logger); - - State = State.Running; - } - - private void MakeMongoBinarysExecutable() - { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || - RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - _fileSystem.MakeFileExecutable(Path.Combine(_mongoBin.Directory, MongoDbDefaults.MongodExecutable)); - _fileSystem.MakeFileExecutable(Path.Combine(_mongoBin.Directory, MongoDbDefaults.MongoExportExecutable)); - _fileSystem.MakeFileExecutable(Path.Combine(_mongoBin.Directory, MongoDbDefaults.MongoImportExecutable)); - } - } - - - private static string GetTemporaryDataDirectory() => Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/MonogDbBinariesNotFoundException.cs b/Mongo2Go-4.1.0/src/Mongo2Go/MonogDbBinariesNotFoundException.cs deleted file mode 100644 index 5845cf18..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/MonogDbBinariesNotFoundException.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Mongo2Go -{ - public class MonogDbBinariesNotFoundException : Exception - { - public MonogDbBinariesNotFoundException() { } - public MonogDbBinariesNotFoundException(string message) : base(message) { } - public MonogDbBinariesNotFoundException(string message, Exception inner) : base(message, inner) { } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/State.cs b/Mongo2Go-4.1.0/src/Mongo2Go/State.cs deleted file mode 100644 index 69e00969..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/State.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Mongo2Go -{ - public enum State - { - Stopped, - Running, - AlreadyRunning - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2Go/packages.lock.json b/Mongo2Go-4.1.0/src/Mongo2Go/packages.lock.json deleted file mode 100644 index e58dba7d..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2Go/packages.lock.json +++ /dev/null @@ -1,490 +0,0 @@ -{ - "version": 1, - "dependencies": { - ".NETFramework,Version=v4.7.2": { - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Direct", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4" - } - }, - "Microsoft.NETFramework.ReferenceAssemblies": { - "type": "Direct", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==", - "dependencies": { - "Microsoft.NETFramework.ReferenceAssemblies.net472": "1.0.3" - } - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[1.0.0, )", - "resolved": "1.0.0", - "contentHash": "aZyGyGg2nFSxix+xMkPmlmZSsnGQ3w+mIG23LTxJZHN+GPwTQ5FpPgDo7RMOq+Kcf5D4hFWfXkGhoGstawX13Q==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "1.0.0", - "Microsoft.SourceLink.Common": "1.0.0" - } - }, - "MinVer": { - "type": "Direct", - "requested": "[2.5.0, )", - "resolved": "2.5.0", - "contentHash": "+vgY+COxnu93nZEVYScloRuboNRIYkElokxTdtKLt6isr/f6GllPt0oLfrHj7fzxgj7SC5xMZg5c2qvd6qyHDQ==" - }, - "MongoDB.Driver": { - "type": "Direct", - "requested": "[3.5.0, )", - "resolved": "3.5.0", - "contentHash": "ST90u7psyMkNNOWFgSkexsrB3kPn7Ynl2DlMFj2rJyYuc6SIxjmzu4ufy51yzM+cPVE1SvVcdb5UFobrRw6cMg==", - "dependencies": { - "DnsClient": "1.6.1", - "Microsoft.Extensions.Logging.Abstractions": "2.0.0", - "MongoDB.Bson": "3.5.0", - "SharpCompress": "0.30.1", - "Snappier": "1.0.0", - "System.Buffers": "4.5.1", - "System.Net.Http": "4.3.4", - "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", - "ZstdSharp.Port": "0.7.3" - } - }, - "SharpCompress": { - "type": "Direct", - "requested": "[0.41.0, )", - "resolved": "0.41.0", - "contentHash": "z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "8.0.0", - "System.Buffers": "4.6.0", - "System.Memory": "4.6.0", - "System.Text.Encoding.CodePages": "8.0.0", - "ZstdSharp.Port": "0.8.6" - } - }, - "System.Text.Json": { - "type": "Direct", - "requested": "[6.0.10, )", - "resolved": "6.0.10", - "contentHash": "NSB0kDipxn2ychp88NXWfFRFlmi1bst/xynOutbnpEfRCT9JZkZ7KOmF/I/hNKo2dILiMGnqblm+j1sggdLB9g==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "6.0.0", - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Text.Encodings.Web": "6.0.0", - "System.Threading.Tasks.Extensions": "4.5.4", - "System.ValueTuple": "4.5.0" - } - }, - "DnsClient": { - "type": "Transitive", - "resolved": "1.6.1", - "contentHash": "4H/f2uYJOZ+YObZjpY9ABrKZI+JNw3uizp6oMzTXwDw6F+2qIPhpRl/1t68O/6e98+vqNiYGu+lswmwdYUy3gg==", - "dependencies": { - "Microsoft.Win32.Registry": "5.0.0", - "System.Buffers": "4.5.1" - } - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==", - "dependencies": { - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "z2fpmmt+1Jfl+ZnBki9nSP08S1/tbEOxFdsK1rSR+LBehIJz1Xv9/6qOOoGNqlwnAGGVGis1Oj6S8Kt9COEYlQ==" - }, - "Microsoft.NETFramework.ReferenceAssemblies.net472": { - "type": "Transitive", - "resolved": "1.0.3", - "contentHash": "0E7evZXHXaDYYiLRfpyXvCh+yzM2rNTyuZDI+ZO7UUqSc6GfjePiXTdqJGtgIKUwdI81tzQKmaWprnUiPj9hAw==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "G8DuQY8/DK5NN+3jm5wcMcd9QYD90UV7MiLmdljSJixi3U/vNaeBKmmXUqI4DJCOeWizIUEh4ALhSt58mR+5eg==" - }, - "Microsoft.Win32.Registry": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", - "dependencies": { - "System.Security.AccessControl": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, - "MongoDB.Bson": { - "type": "Transitive", - "resolved": "3.5.0", - "contentHash": "JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "5.0.0" - } - }, - "Snappier": { - "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "rFtK2KEI9hIe8gtx3a0YDXdHOpedIf9wYCEYtBEmtlyiWVX3XlCNV03JrmmAi/Cdfn7dxK+k0sjjcLv4fpHnqA==", - "dependencies": { - "System.Memory": "4.5.4", - "System.Runtime.CompilerServices.Unsafe": "4.7.1", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA==" - }, - "System.IO": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==" - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg==", - "dependencies": { - "System.Buffers": "4.6.0", - "System.Numerics.Vectors": "4.6.0", - "System.Runtime.CompilerServices.Unsafe": "6.1.0" - } - }, - "System.Net.Http": { - "type": "Transitive", - "resolved": "4.3.4", - "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", - "dependencies": { - "System.Security.Cryptography.X509Certificates": "4.3.0" - } - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "t+SoieZsRuEyiw/J+qXUbolyO219tKQQI0+2/YI+Qv7YdGValA6WiuokrNKqjrTNsy5ABWU11bdKOzUdheteXg==" - }, - "System.Runtime": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.1.0", - "contentHash": "5o/HZxx6RVqYlhKSq8/zronDkALJZUT2Vz0hx43f0gwe8mwlM0y2nYlqdBwLMzr262Bwvpikeb/yEwkAa5PADg==" - }, - "System.Runtime.InteropServices.RuntimeInformation": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==" - }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", - "dependencies": { - "System.Security.Principal.Windows": "5.0.0" - } - }, - "System.Security.Cryptography.Algorithms": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", - "dependencies": { - "System.IO": "4.3.0", - "System.Runtime": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0", - "System.Security.Cryptography.Primitives": "4.3.0" - } - }, - "System.Security.Cryptography.Encoding": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==" - }, - "System.Security.Cryptography.Primitives": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==" - }, - "System.Security.Cryptography.X509Certificates": { - "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", - "dependencies": { - "System.Security.Cryptography.Algorithms": "4.3.0", - "System.Security.Cryptography.Encoding": "4.3.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "System.ValueTuple": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" - }, - "ZstdSharp.Port": { - "type": "Transitive", - "resolved": "0.8.6", - "contentHash": "iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - } - }, - ".NETStandard,Version=v2.1": { - "Microsoft.Extensions.Logging.Abstractions": { - "type": "Direct", - "requested": "[6.0.0, )", - "resolved": "6.0.0", - "contentHash": "/HggWBbTwy8TgebGSX5DBZ24ndhzi93sHUBDvP1IxbZD7FDokYzdAr6+vbWGjw2XAfR2EJ1sfKUotpjHnFWPxA==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4" - } - }, - "Microsoft.NETFramework.ReferenceAssemblies": { - "type": "Direct", - "requested": "[1.0.3, )", - "resolved": "1.0.3", - "contentHash": "vUc9Npcs14QsyOD01tnv/m8sQUnGTGOw1BCmKcv77LBJY7OxhJ+zJF7UD/sCL3lYNFuqmQEVlkfS4Quif6FyYg==", - "dependencies": { - "Microsoft.NETFramework.ReferenceAssemblies.net461": "1.0.3" - } - }, - "Microsoft.SourceLink.GitHub": { - "type": "Direct", - "requested": "[1.0.0, )", - "resolved": "1.0.0", - "contentHash": "aZyGyGg2nFSxix+xMkPmlmZSsnGQ3w+mIG23LTxJZHN+GPwTQ5FpPgDo7RMOq+Kcf5D4hFWfXkGhoGstawX13Q==", - "dependencies": { - "Microsoft.Build.Tasks.Git": "1.0.0", - "Microsoft.SourceLink.Common": "1.0.0" - } - }, - "MinVer": { - "type": "Direct", - "requested": "[2.5.0, )", - "resolved": "2.5.0", - "contentHash": "+vgY+COxnu93nZEVYScloRuboNRIYkElokxTdtKLt6isr/f6GllPt0oLfrHj7fzxgj7SC5xMZg5c2qvd6qyHDQ==" - }, - "MongoDB.Driver": { - "type": "Direct", - "requested": "[3.5.0, )", - "resolved": "3.5.0", - "contentHash": "ST90u7psyMkNNOWFgSkexsrB3kPn7Ynl2DlMFj2rJyYuc6SIxjmzu4ufy51yzM+cPVE1SvVcdb5UFobrRw6cMg==", - "dependencies": { - "DnsClient": "1.6.1", - "Microsoft.Extensions.Logging.Abstractions": "2.0.0", - "MongoDB.Bson": "3.5.0", - "SharpCompress": "0.30.1", - "Snappier": "1.0.0", - "System.Buffers": "4.5.1", - "ZstdSharp.Port": "0.7.3" - } - }, - "SharpCompress": { - "type": "Direct", - "requested": "[0.41.0, )", - "resolved": "0.41.0", - "contentHash": "z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "8.0.0", - "System.Buffers": "4.6.0", - "System.Memory": "4.6.0", - "System.Text.Encoding.CodePages": "8.0.0", - "ZstdSharp.Port": "0.8.6" - } - }, - "System.Text.Json": { - "type": "Direct", - "requested": "[6.0.10, )", - "resolved": "6.0.10", - "contentHash": "NSB0kDipxn2ychp88NXWfFRFlmi1bst/xynOutbnpEfRCT9JZkZ7KOmF/I/hNKo2dILiMGnqblm+j1sggdLB9g==", - "dependencies": { - "Microsoft.Bcl.AsyncInterfaces": "6.0.0", - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0", - "System.Text.Encodings.Web": "6.0.0", - "System.Threading.Tasks.Extensions": "4.5.4" - } - }, - "DnsClient": { - "type": "Transitive", - "resolved": "1.6.1", - "contentHash": "4H/f2uYJOZ+YObZjpY9ABrKZI+JNw3uizp6oMzTXwDw6F+2qIPhpRl/1t68O/6e98+vqNiYGu+lswmwdYUy3gg==", - "dependencies": { - "Microsoft.Win32.Registry": "5.0.0" - } - }, - "Microsoft.Bcl.AsyncInterfaces": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "3WA9q9yVqJp222P3x1wYIGDAkpjAku0TMUaaQV22g6L67AI0LdOIrVS7Ht2vJfLHGSPVuqN94vIr15qn+HEkHw==" - }, - "Microsoft.Build.Tasks.Git": { - "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "z2fpmmt+1Jfl+ZnBki9nSP08S1/tbEOxFdsK1rSR+LBehIJz1Xv9/6qOOoGNqlwnAGGVGis1Oj6S8Kt9COEYlQ==" - }, - "Microsoft.NETFramework.ReferenceAssemblies.net461": { - "type": "Transitive", - "resolved": "1.0.3", - "contentHash": "AmOJZwCqnOCNp6PPcf9joyogScWLtwy0M1WkqfEQ0M9nYwyDD7EX9ZjscKS5iYnyvteX7kzSKFCKt9I9dXA6mA==" - }, - "Microsoft.SourceLink.Common": { - "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "G8DuQY8/DK5NN+3jm5wcMcd9QYD90UV7MiLmdljSJixi3U/vNaeBKmmXUqI4DJCOeWizIUEh4ALhSt58mR+5eg==" - }, - "Microsoft.Win32.Registry": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4", - "System.Security.AccessControl": "5.0.0", - "System.Security.Principal.Windows": "5.0.0" - } - }, - "MongoDB.Bson": { - "type": "Transitive", - "resolved": "3.5.0", - "contentHash": "JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "5.0.0" - } - }, - "Snappier": { - "type": "Transitive", - "resolved": "1.0.0", - "contentHash": "rFtK2KEI9hIe8gtx3a0YDXdHOpedIf9wYCEYtBEmtlyiWVX3XlCNV03JrmmAi/Cdfn7dxK+k0sjjcLv4fpHnqA==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.7.1" - } - }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "lN6tZi7Q46zFzAbRYXTIvfXcyvQQgxnY7Xm6C6xQ9784dEL1amjM6S6Iw4ZpsvesAKnRVsM4scrDQaDqSClkjA==" - }, - "System.Memory": { - "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg==", - "dependencies": { - "System.Buffers": "4.6.0", - "System.Numerics.Vectors": "4.6.0", - "System.Runtime.CompilerServices.Unsafe": "6.1.0" - } - }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "t+SoieZsRuEyiw/J+qXUbolyO219tKQQI0+2/YI+Qv7YdGValA6WiuokrNKqjrTNsy5ABWU11bdKOzUdheteXg==" - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.1.0", - "contentHash": "5o/HZxx6RVqYlhKSq8/zronDkALJZUT2Vz0hx43f0gwe8mwlM0y2nYlqdBwLMzr262Bwvpikeb/yEwkAa5PADg==" - }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "dagJ1mHZO3Ani8GH0PHpPEe/oYO+rVdbQjvjJkBRNQkX4t0r1iaeGn8+/ybkSLEan3/slM0t59SVdHzuHf2jmw==", - "dependencies": { - "System.Security.Principal.Windows": "5.0.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, - "System.Text.Encoding.CodePages": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "OZIsVplFGaVY90G2SbpgU7EnCoOO5pw1t4ic21dBF3/1omrJFpAGoNAVpPyMVOC90/hvgkGG3VFqR13YgZMQfg==", - "dependencies": { - "System.Memory": "4.5.5", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Text.Encodings.Web": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", - "dependencies": { - "System.Buffers": "4.5.1", - "System.Memory": "4.5.4", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.4", - "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.3" - } - }, - "ZstdSharp.Port": { - "type": "Transitive", - "resolved": "0.8.6", - "contentHash": "iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "6.0.0" - } - } - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/FolderSearchTests.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/FolderSearchTests.cs deleted file mode 100644 index f3a2d9c4..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/FolderSearchTests.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using FluentAssertions; -using Machine.Specifications; -using Mongo2Go.Helper; - -// ReSharper disable InconsistentNaming -// ReSharper disable UnusedMember.Local -namespace Mongo2GoTests -{ - [Subject("FolderSearch")] - public class when_requesting_current_executing_directory - { - public static string directory; - - Because of = () => directory = FolderSearch.CurrentExecutingDirectory(); - It should_contain_correct_path = () => directory.Should().Contain(Path.Combine("Mongo2GoTests", "bin")); - } - - [Subject("FolderSearch")] - public class when_searching_for_folder : FolderSearchSpec - { - static string startDirectory = Path.Combine(BaseDir, "test1", "test2"); - static string searchPattern = Path.Combine("packages", "Mongo2Go*", "tools", "mongodb-win32-i386*", "bin"); - static string directory; - - Because of = () => directory = startDirectory.FindFolder(searchPattern); - It should_find_the_path_with_the_highest_version_number = () => directory.Should().Be(MongoBinaries); - } - - - [Subject("FolderSearch")] - public class when_searching_for_not_existing_folder : FolderSearchSpec - { - static string startDirectory = Path.Combine(BaseDir, "test1", "test2"); - static string searchPattern = Path.Combine("packages", "Mongo2Go*", "XXX", "mongodb-win32-i386*", "bin"); - static string directory; - - Because of = () => directory = startDirectory.FindFolder(searchPattern); - It should_return_null = () => directory.Should().BeNull(); - } - - [Subject("FolderSearch")] - public class when_searching_for_not_existing_start_dir : FolderSearchSpec - { - static string startDirectory = Path.Combine(Path.GetRandomFileName()); - static string searchPattern = Path.Combine("packages", "Mongo2Go*", "XXX", "mongodb-win32-i386*", "bin"); - static string directory; - - Because of = () => directory = startDirectory.FindFolder(searchPattern); - It should_return_null = () => directory.Should().BeNull(); - } - - [Subject("FolderSearch")] - public class when_searching_for_folder_upwards : FolderSearchSpec - { - static string searchPattern = Path.Combine("packages", "Mongo2Go*", "tools", "mongodb-win32-i386*", "bin"); - static string directory; - - Because of = () => directory = LocationOfAssembly.FindFolderUpwards(searchPattern); - It should_find_the_path_with_the_highest_version_number = () => directory.Should().Be(MongoBinaries); - } - - [Subject("FolderSearch")] - public class when_searching_for_not_existing_folder_upwards : FolderSearchSpec - { - static string searchPattern = Path.Combine("packages", "Mongo2Go*", "XXX", "mongodb-win32-i386*", "bin"); - static string directory; - - Because of = () => directory = LocationOfAssembly.FindFolderUpwards(searchPattern); - It should_return_null = () => directory.Should().BeNull(); - } - - [Subject("FolderSearch")] - public class when_remove_last_part_of_path - { - static string directory; - - Because of = () => directory = Path.Combine("test1", "test2", "test3").RemoveLastPart(); - It should_remove_the_element = () => directory.Should().Be(Path.Combine("test1", "test2")); - } - - [Subject("FolderSearch")] - public class when_remove_last_part_of_single_element_path - { - static string directory; - - Because of = () => directory = "test1".RemoveLastPart(); - It should_return_null = () => directory.Should().BeNull(); - } - - [Subject("FolderSearch")] - public class when_directory_contains_multiple_versions_mongo2go - { - private readonly string[] directories; - - private static string getAssemblyVersion() - { - // ReSharper disable once PossibleNullReferenceException - return typeof(FolderSearch).GetTypeInfo().Assembly.GetCustomAttribute().InformationalVersion; - } - - public when_directory_contains_multiple_versions_mongo2go() - { - - // setup some directories - directories = new[] - { - Path.Combine(AppDomain.CurrentDomain.BaseDirectory, getAssemblyVersion() + "a"), - Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "2.2.9"), - Path.Combine(AppDomain.CurrentDomain.BaseDirectory, getAssemblyVersion()) - }; - - foreach (var d in directories) - Directory.CreateDirectory(d); - } - - private static string path; - - private Because of = () => path = FolderSearch.FindFolder(AppDomain.CurrentDomain.BaseDirectory, "*"); - - private It should_return_the_one_that_matches_our_own_assembly_version = - () => path.Should().Be(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, getAssemblyVersion())); - } - - public class FolderSearchSpec - { - public static string BaseDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - public static string MongoBinaries = Path.Combine(BaseDir, "test1", "test2", "packages", "Mongo2Go.1.2.3", "tools", "mongodb-win32-i386-2.0.7-rc0", "bin"); - public static string MongoOlderBinaries = Path.Combine(BaseDir, "test1", "test2", "packages", "Mongo2Go.1.1.1", "tools", "mongodb-win32-i386-2.0.7-rc0", "bin"); - public static string LocationOfAssembly = Path.Combine(BaseDir, "test1", "test2", "Project", "bin"); - - Establish context = () => - { - if (!Directory.Exists(BaseDir)) { Directory.CreateDirectory(BaseDir); } - if (!Directory.Exists(MongoBinaries)) { Directory.CreateDirectory(MongoBinaries); } - if (!Directory.Exists(MongoOlderBinaries)) { Directory.CreateDirectory(MongoOlderBinaries); } - if (!Directory.Exists(LocationOfAssembly)) { Directory.CreateDirectory(LocationOfAssembly); } - }; - - Cleanup stuff = () => { if (Directory.Exists(BaseDir)) { Directory.Delete(BaseDir, true); }}; - } -} -// ReSharper restore UnusedMember.Local -// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Mongo2GoTests.csproj b/Mongo2Go-4.1.0/src/Mongo2GoTests/Mongo2GoTests.csproj deleted file mode 100644 index 7c596c21..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Mongo2GoTests.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - net8.0 - false - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/MongoDbAdditionalArgumentsTests.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/MongoDbAdditionalArgumentsTests.cs deleted file mode 100644 index 1ec07138..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/MongoDbAdditionalArgumentsTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -using FluentAssertions; -using Machine.Specifications; -using Mongo2Go.Helper; -using System; - -// ReSharper disable InconsistentNaming -// ReSharper disable UnusedMember.Local -namespace Mongo2GoTests -{ - [Subject(typeof(MongodArguments))] - public class when_null_additional_arguments_return_empty_string - { - private static string validAdditionalArguments; - - Because of = () => validAdditionalArguments = MongodArguments.GetValidAdditionalArguments(string.Empty, null); - It should_be_empty_string = () => validAdditionalArguments.Should().BeEmpty(); - } - - [Subject(typeof(MongodArguments))] - public class when_no_additional_arguments_return_empty_string - { - private static string validAdditionalArguments; - - Because of = () => validAdditionalArguments = MongodArguments.GetValidAdditionalArguments(string.Empty, string.Empty); - It should_be_empty_string = () => validAdditionalArguments.Should().BeEmpty(); - } - - [Subject(typeof(MongodArguments))] - public class when_additional_arguments_start_with_argument_separator_return_additional_arguments - { - private static string validAdditionalArguments; - private const string additionalArgumentsUnderTest = " --argument_1 under_test --argument_2 under test"; - private const string expectedAdditionalArguments = " --argument_1 under_test --argument_2 under test"; - - Because of = () => validAdditionalArguments = MongodArguments.GetValidAdditionalArguments(string.Empty, additionalArgumentsUnderTest); - It should_be_expected_additional_arguments = () => validAdditionalArguments.Should().Be(expectedAdditionalArguments); - } - - [Subject(typeof(MongodArguments))] - public class when_additional_arguments_does_not_start_with_argument_separator_return_additional_arguments - { - private static string validAdditionalArguments; - private const string additionalArgumentsUnderTest = "argument_1 under_test --argument_2 under test"; - private const string expectedAdditionalArguments = " --argument_1 under_test --argument_2 under test"; - - Because of = () => validAdditionalArguments = MongodArguments.GetValidAdditionalArguments(string.Empty, additionalArgumentsUnderTest); - It should_be_expected_additional_arguments = () => validAdditionalArguments.Should().Be(expectedAdditionalArguments); - } - - [Subject(typeof(MongodArguments))] - public class when_existing_arguments_and_additional_arguments_do_not_have_shared_options_return_additional_arguments - { - private static string validAdditionalArguments; - private const string existingArguments = "--existing_argument1 --existing_argument2"; - private const string additionalArgumentsUnderTest = " --argument_1 under_test --argument_2 under test"; - private const string expectedAdditionalArguments = " --argument_1 under_test --argument_2 under test"; - - Because of = () => validAdditionalArguments = MongodArguments.GetValidAdditionalArguments(existingArguments, additionalArgumentsUnderTest); - It should_be_expected_additional_arguments = () => validAdditionalArguments.Should().Be(expectedAdditionalArguments); - } - - [Subject(typeof(MongodArguments))] - public class when_existing_arguments_and_additional_arguments_have_shared_options_throw_argument_exception - { - private static Exception exception; - private const string duplicateArgument = "existing_argument2"; - private static readonly string existingArguments = $"--existing_argument1 --{duplicateArgument}"; - private static readonly string additionalArgumentsUnderTest = $" --argument_1 under_test --{duplicateArgument} argument2_new_value --argument_2 under test"; - - Because of = () => exception = Catch.Exception(() => MongodArguments.GetValidAdditionalArguments(existingArguments, additionalArgumentsUnderTest)); - It should_throw_argument_exception = () => exception.Should().BeOfType(); - It should_contain_more_than_instance_of_the_duplicate_argument = () => exception.Message.IndexOf(duplicateArgument, StringComparison.InvariantCultureIgnoreCase).Should().NotBe(exception.Message.LastIndexOf(duplicateArgument, StringComparison.InvariantCultureIgnoreCase)); - } -} -// ReSharper restore UnusedMember.Local -// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoDebuggingTest.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoDebuggingTest.cs deleted file mode 100644 index 0cbe12a7..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoDebuggingTest.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Mongo2Go; -using MongoDB.Bson; -using MongoDB.Bson.Serialization; -using MongoDB.Driver; - -namespace Mongo2GoTests.Runner -{ - public class MongoDebuggingTest - { - internal static MongoDbRunner _runner; - internal static IMongoCollection _collection; - internal static string _databaseName = "IntegrationTest"; - internal static string _collectionName = "TestCollection"; - internal static IMongoDatabase _database; - - internal static void CreateConnection() - { - _runner = MongoDbRunner.StartForDebugging(singleNodeReplSet: false); - - MongoClient client = new MongoClient(_runner.ConnectionString); - _database = client.GetDatabase(_databaseName); - _collection = _database.GetCollection(_collectionName); - } - - public static IList ReadBsonFile(string fileName) - { - string[] content = File.ReadAllLines(fileName); - return content.Select(s => BsonSerializer.Deserialize(s)).ToList(); - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoIntegrationTest.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoIntegrationTest.cs deleted file mode 100644 index 3ff56ff4..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoIntegrationTest.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Microsoft.Extensions.Logging; -using Mongo2Go; -using MongoDB.Driver; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Mongo2GoTests.Runner -{ - public class MongoIntegrationTest - { - internal static MongoDbRunner _runner; - internal static IMongoCollection _collection; - internal static string _databaseName = "IntegrationTest"; - internal static string _collectionName = "TestCollection"; - - internal static void CreateConnection(ILogger logger = null) - { - _runner = MongoDbRunner.Start(singleNodeReplSet: false, logger: logger); - - MongoClient client = new MongoClient(_runner.ConnectionString); - IMongoDatabase database = client.GetDatabase(_databaseName); - _collection = database.GetCollection(_collectionName); - } - } - - public static class TaskExtensions - { - public static async Task WithTimeout(this Task task, TimeSpan timeout) - { - using (var cancellationTokenSource = new CancellationTokenSource()) - { - - var completedTask = await Task.WhenAny(task, Task.Delay(timeout, cancellationTokenSource.Token)); - if (completedTask == task) - { - cancellationTokenSource.Cancel(); - await task; - } - else - { - throw new TimeoutException("The operation has timed out."); - } - } - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoTransactionTest.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoTransactionTest.cs deleted file mode 100644 index 9caa6dc9..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/MongoTransactionTest.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using Mongo2Go; -using MongoDB.Driver; - -namespace Mongo2GoTests.Runner -{ - public class MongoTransactionTest - { - internal static MongoDbRunner _runner; - internal static IMongoCollection _mainCollection; - internal static IMongoCollection _dependentCollection; - internal static string _databaseName = "TransactionTest"; - internal static string _mainCollectionName = "MainCollection"; - internal static string _dependentCollectionName = "DependentCollection"; - internal static IMongoDatabase database; - internal static IMongoClient client; - internal static void CreateConnection(ushort? singleNodeReplSetWaitTimeout = null) - { - if (singleNodeReplSetWaitTimeout.HasValue) - { - _runner = MongoDbRunner.Start(singleNodeReplSet: true, singleNodeReplSetWaitTimeout: singleNodeReplSetWaitTimeout.Value); - } - else - { - _runner = MongoDbRunner.Start(singleNodeReplSet: true); - } - - client = new MongoClient(_runner.ConnectionString); - database = client.GetDatabase(_databaseName); - _mainCollection = database.GetCollection(_mainCollectionName); - _dependentCollection = database.GetCollection(_dependentCollectionName); - } - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerImportExportTests.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerImportExportTests.cs deleted file mode 100644 index 3a219669..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerImportExportTests.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using FluentAssertions; -using Machine.Specifications; -using Mongo2Go.Helper; -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using It = Machine.Specifications.It; - -// ReSharper disable InconsistentNaming -// ReSharper disable UnusedMember.Local -namespace Mongo2GoTests.Runner -{ - [Subject("Runner Integration Test")] - public class when_using_monogoexport : MongoDebuggingTest - { - static readonly string _testFile = Path.GetTempPath() + "testExport.json"; - static IList parsedContent; - - Establish context = () => - - { - CreateConnection(); - _database.DropCollection(_collectionName); - - _collection.InsertOne(TestDocument.DummyData1()); - _collection.InsertOne(TestDocument.DummyData2()); - _collection.InsertOne(TestDocument.DummyData3()); - }; - - Because of = () => - { - _runner.Export(_databaseName, _collectionName, _testFile); - Thread.Sleep(500); - parsedContent = ReadBsonFile(_testFile); - }; - - It should_preserve_all_values1 = () => parsedContent[0].Should().BeEquivalentTo(TestDocument.DummyData1(), cfg => cfg.Excluding(d => d.Id)); - It should_preserve_all_values2 = () => parsedContent[1].Should().BeEquivalentTo(TestDocument.DummyData2(), cfg => cfg.Excluding(d => d.Id)); - It should_preserve_all_values3 = () => parsedContent[2].Should().BeEquivalentTo(TestDocument.DummyData3(), cfg => cfg.Excluding(d => d.Id)); - - Cleanup stuff = () => - { - new FileSystem().DeleteFile(_testFile); - _runner.Dispose(); - }; - } - - [Subject("Runner Integration Test")] - public class when_using_monogoimport : MongoDebuggingTest - { - static IQueryable query; - static readonly string _testFile = Path.GetTempPath() + "testImport.json"; - - const string _filecontent = - @"{ ""_id"" : { ""$oid"" : ""50227b375dff9218248eadc4"" }, ""StringTest"" : ""Hello World"", ""IntTest"" : 42, ""DateTest"" : { ""$date"" : ""1984-09-30T06:06:06.171Z"" }, ""ListTest"" : [ ""I"", ""am"", ""a"", ""list"", ""of"", ""strings"" ] }" + "\r\n" + - @"{ ""_id"" : { ""$oid"" : ""50227b375dff9218248eadc5"" }, ""StringTest"" : ""Foo"", ""IntTest"" : 23, ""DateTest"" : null, ""ListTest"" : null }" + "\r\n" + - @"{ ""_id"" : { ""$oid"" : ""50227b375dff9218248eadc6"" }, ""StringTest"" : ""Bar"", ""IntTest"" : 77, ""DateTest"" : null, ""ListTest"" : null }" + "\r\n"; - - Establish context = () => - { - CreateConnection(); - _database.DropCollection(_collectionName); - File.WriteAllText(_testFile, _filecontent); - }; - - Because of = () => - { - _runner.Import(_databaseName, _collectionName, _testFile, true); - Thread.Sleep(500); - query = _collection.AsQueryable().Select(c => c).OrderBy(c => c.Id); ; - - }; - - It should_return_document1 = () => query.ToList().ElementAt(0).Should().BeEquivalentTo(TestDocument.DummyData1(), cfg => cfg.Excluding(d => d.Id)); - It should_return_document2 = () => query.ToList().ElementAt(1).Should().BeEquivalentTo(TestDocument.DummyData2(), cfg => cfg.Excluding(d => d.Id)); - It should_return_document3 = () => query.ToList().ElementAt(2).Should().BeEquivalentTo(TestDocument.DummyData3(), cfg => cfg.Excluding(d => d.Id)); - - Cleanup stuff = () => - { - new FileSystem().DeleteFile(_testFile); - _runner.Dispose(); - }; - } -} -// ReSharper restore UnusedMember.Local -// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerIntegrationTests.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerIntegrationTests.cs deleted file mode 100644 index 3af3a881..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerIntegrationTests.cs +++ /dev/null @@ -1,118 +0,0 @@ -using FluentAssertions; -using Machine.Specifications; -using MELT; -using MongoDB.Driver; -using MongoDB.Driver.Linq; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using It = Machine.Specifications.It; - -// ReSharper disable InconsistentNaming -// ReSharper disable UnusedMember.Local -namespace Mongo2GoTests.Runner -{ - [Subject("Runner Integration Test")] - public class when_using_the_inbuild_serialization : MongoIntegrationTest - { - static TestDocument findResult; - - - Establish context = () => - { - CreateConnection(); - _collection.InsertOne(TestDocument.DummyData1()); - }; - - Because of = () => findResult = _collection.FindSync(_ => true).First(); - - It should_return_a_result = () => findResult.Should().NotBeNull(); - It should_hava_expected_data = () => findResult.Should().BeEquivalentTo(TestDocument.DummyData1(), cfg => cfg.Excluding(d => d.Id)); - - Cleanup stuff = () => _runner.Dispose(); - } - - [Subject("Runner Integration Test")] - public class when_using_the_new_linq_support : MongoIntegrationTest - { - static List queryResult; - - Establish context = () => - { - CreateConnection(); - _collection.InsertOne(TestDocument.DummyData1()); - _collection.InsertOne(TestDocument.DummyData2()); - _collection.InsertOne(TestDocument.DummyData3()); - }; - - Because of = () => - { - queryResult = (from c in _collection.AsQueryable() - where c.StringTest == TestDocument.DummyData2().StringTest || c.StringTest == TestDocument.DummyData3().StringTest - select c).ToList(); - }; - - It should_return_two_documents = () => queryResult.Count().Should().Be(2); - It should_return_document2 = () => queryResult.ElementAt(0).IntTest = TestDocument.DummyData2().IntTest; - It should_return_document3 = () => queryResult.ElementAt(1).IntTest = TestDocument.DummyData3().IntTest; - - Cleanup stuff = () => _runner.Dispose(); - } - - [Subject("Runner Integration Test")] - public class when_using_commands_that_create_console_output : MongoIntegrationTest - { - static List taskList = new List(); - - private Establish context = () => - { - CreateConnection(); - }; - - private Because of = () => - { - var createIndexModel = new CreateIndexModel(Builders.IndexKeys.Ascending(x => x.IntTest)); - taskList.Add(_collection.Indexes.CreateOneAsync(createIndexModel).WithTimeout(TimeSpan.FromMilliseconds(5000))); - taskList.Add(_collection.Indexes.DropAllAsync().WithTimeout(TimeSpan.FromMilliseconds(5000))); - }; - - It should_not_timeout = () => Task.WaitAll(taskList.ToArray()); - - Cleanup stuff = () => _runner.Dispose(); - } - - - [Subject("Runner Integration Test")] - public class when_using_microsoft_ilogger : MongoIntegrationTest - { - static List taskList = new List(); - static ITestLoggerFactory loggerFactory; - - private Establish context = () => - { - loggerFactory = TestLoggerFactory.Create(); - var logger = loggerFactory.CreateLogger("MyTestLogger"); - CreateConnection(logger); - }; - - private Because of = () => - { - var createIndexModel = new CreateIndexModel(Builders.IndexKeys.Ascending(x => x.IntTest)); - taskList.Add(_collection.Indexes.CreateOneAsync(createIndexModel).WithTimeout(TimeSpan.FromMilliseconds(5000))); - taskList.Add(_collection.Indexes.DropAllAsync().WithTimeout(TimeSpan.FromMilliseconds(5000))); - }; - - It should_not_timeout = () => Task.WaitAll(taskList.ToArray()); - It should_have_received_many_logs = () => - loggerFactory.Sink.LogEntries.Count(l => l.LogLevel == Microsoft.Extensions.Logging.LogLevel.Information) - .Should().BeGreaterThan(10); - It should_have_created_collection_statement = () => loggerFactory.Sink.LogEntries - .Count(l => l.Properties.Any(p => p.Key == "message" && (string)p.Value == "createCollection")) - .Should().BeGreaterOrEqualTo(1); - - Cleanup stuff = () => _runner.Dispose(); - } -} -// ReSharper restore UnusedMember.Local -// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTests.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTests.cs deleted file mode 100644 index 9d3be52c..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTests.cs +++ /dev/null @@ -1,108 +0,0 @@ -using FluentAssertions; -using Machine.Specifications; -using Mongo2Go; -using Mongo2Go.Helper; -using Moq; -using System.IO; -using It = Machine.Specifications.It; - -#pragma warning disable CS0618 // Type or member is obsolete - -// ReSharper disable InconsistentNaming -// ReSharper disable UnusedMember.Local - -namespace Mongo2GoTests.Runner -{ - [Subject("Runner")] - public class when_instantiating_the_runner_for_integration_test - { - static MongoDbRunner runner; - static Mock portPoolMock; - static Mock fileSystemMock; - static Mock processStarterMock; - static Mock binaryLocatorMock; - - static string exptectedDataDirectory; - static string exptectedLogfile; - static readonly string exptectedConnectString = "mongodb://127.0.0.1:{0}/".Formatted(MongoDbDefaults.TestStartPort + 1); - - Establish context = () => - { - portPoolMock = new Mock(); - portPoolMock.Setup(m => m.GetNextOpenPort()).Returns(MongoDbDefaults.TestStartPort + 1); - - fileSystemMock = new Mock(); - fileSystemMock.Setup(m => m.CreateFolder(Moq.It.IsAny())).Callback(s => - { - exptectedDataDirectory = s; - exptectedLogfile = Path.Combine(exptectedDataDirectory, MongoDbDefaults.Lockfile); - }); - - var processMock = new Mock(); - - processStarterMock = new Mock(); - processStarterMock.Setup(m => m.Start(Moq.It.IsAny(), Moq.It.IsAny(), Moq.It.IsAny(), false, Moq.It.IsAny(), Moq.It.IsAny(), null)).Returns(processMock.Object); - - binaryLocatorMock = new Mock (); - binaryLocatorMock.Setup(m => m.Directory).Returns(string.Empty); - }; - - Because of = () => runner = MongoDbRunner.StartUnitTest(portPoolMock.Object, fileSystemMock.Object, processStarterMock.Object, binaryLocatorMock.Object); - - It should_create_the_data_directory = () => fileSystemMock.Verify(x => x.CreateFolder(Moq.It.Is(s => s.StartsWith(Path.GetTempPath()))), Times.Exactly(1)); - It should_delete_old_lock_file = () => fileSystemMock.Verify(x => x.DeleteFile(exptectedLogfile), Times.Exactly(1)); - - It should_start_the_process = () => processStarterMock.Verify(x => x.Start(Moq.It.IsAny(), Moq.It.IsAny(), Moq.It.IsAny(), false, Moq.It.IsAny(), Moq.It.IsAny(), null), Times.Exactly(1)); - - It should_have_expected_connection_string = () => runner.ConnectionString.Should().Be(exptectedConnectString); - It should_return_an_instance_with_state_running = () => runner.State.Should().Be(State.Running); - } - - [Subject("Runner")] - public class when_instantiating_the_runner_for_local_debugging - { - static MongoDbRunner runner; - static Mock portWatcherMock; - static Mock processWatcherMock; - static Mock fileSystemMock; - static Mock processStarterMock; - static Mock binaryLocatorMock; - - static string exptectedDataDirectory; - static string exptectedLogfile; - - Establish context = () => - { - processWatcherMock = new Mock(); - processWatcherMock.Setup(m => m.IsProcessRunning(Moq.It.IsAny())).Returns(false); - - portWatcherMock = new Mock(); - portWatcherMock.Setup(m => m.IsPortAvailable(Moq.It.IsAny())).Returns(true); - - fileSystemMock = new Mock(); - fileSystemMock.Setup(m => m.CreateFolder(Moq.It.IsAny())).Callback(s => - { - exptectedDataDirectory = s; - exptectedLogfile = Path.Combine(exptectedDataDirectory, MongoDbDefaults.Lockfile); - }); - - var processMock = new Mock(); - processStarterMock = new Mock(); - processStarterMock.Setup(m => m.Start(Moq.It.IsAny(), exptectedDataDirectory, MongoDbDefaults.DefaultPort, true, false, Moq.It.IsAny(), Moq.It.IsAny(), null)).Returns(processMock.Object); - - binaryLocatorMock = new Mock (); - binaryLocatorMock.Setup(m => m.Directory).Returns(string.Empty); - }; - - Because of = () => runner = MongoDbRunner.StartForDebuggingUnitTest(processWatcherMock.Object, portWatcherMock.Object, fileSystemMock.Object, processStarterMock.Object, binaryLocatorMock.Object); - - It should_check_for_already_running_process = () => processWatcherMock.Verify(x => x.IsProcessRunning(MongoDbDefaults.ProcessName), Times.Exactly(1)); - It should_check_the_default_port = () => portWatcherMock.Verify(x => x.IsPortAvailable(MongoDbDefaults.DefaultPort), Times.Exactly(1)); - It should_create_the_data_directory = () => fileSystemMock.Verify(x => x.CreateFolder(Moq.It.Is(s => s.StartsWith(Path.GetTempPath()))), Times.Exactly(1)); - It should_delete_old_lock_file = () => fileSystemMock.Verify(x => x.DeleteFile(exptectedLogfile), Times.Exactly(1)); - It should_return_an_instance_with_state_running = () => runner.State.Should().Be(State.Running); - It should_start_the_process_without_kill = () => processStarterMock.Verify(x => x.Start(Moq.It.IsAny(), exptectedDataDirectory, MongoDbDefaults.DefaultPort, true, false, Moq.It.IsAny(), Moq.It.IsAny(), null), Times.Exactly(1)); - } -} -// ReSharper restore UnusedMember.Local -// ReSharper restore InconsistentNaming \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTransactionTests.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTransactionTests.cs deleted file mode 100644 index 612794c1..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/RunnerTransactionTests.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using FluentAssertions; -using Machine.Specifications; -using MongoDB.Driver; - -namespace Mongo2GoTests.Runner -{ - [Subject("Runner Transaction Test")] - public class when_transaction_completes : MongoTransactionTest - { - private static TestDocument mainDocument; - private static TestDocument dependentDocument; - - Establish context = () => - - { - CreateConnection(); - database.DropCollection(_mainCollectionName); - database.DropCollection(_dependentCollectionName); - _mainCollection.InsertOne(TestDocument.DummyData2()); - _dependentCollection.InsertOne(TestDocument.DummyData2()); - }; - - private Because of = () => - { - var filter = Builders.Filter.Where(x => x.IntTest == 23); - var update = Builders.Update.Inc(i => i.IntTest, 10); - - using (var sessionHandle = client.StartSession()) - { - try - { - var i = 0; - while (i < 10) - { - try - { - i++; - sessionHandle.StartTransaction(new TransactionOptions( - readConcern: ReadConcern.Local, - writeConcern: WriteConcern.W1)); - try - { - var first = _mainCollection.UpdateOne(sessionHandle, filter, update); - var second = _dependentCollection.UpdateOne(sessionHandle, filter, update); - } - catch (Exception) - { - sessionHandle.AbortTransaction(); - throw; - } - - var j = 0; - while (j < 10) - { - try - { - j++; - sessionHandle.CommitTransaction(); - break; - } - catch (MongoException e) - { - if (e.HasErrorLabel("UnknownTransactionCommitResult")) - continue; - throw; - } - } - break; - } - catch (MongoException e) - { - if (e.HasErrorLabel("TransientTransactionError")) - continue; - throw; - } - } - } - catch (Exception) - { - - } - } - - mainDocument = _mainCollection.FindSync(Builders.Filter.Empty).FirstOrDefault(); - dependentDocument = _dependentCollection.FindSync(Builders.Filter.Empty).FirstOrDefault(); - }; - - It main_should_be_33 = () => mainDocument.IntTest.Should().Be(33); - It dependent_should_be_33 = () => dependentDocument.IntTest.Should().Be(33); - Cleanup cleanup = () => _runner.Dispose(); - } - - - [Subject("Runner Transaction Test")] - public class when_transaction_is_aborted_before_commit : MongoTransactionTest - { - private static TestDocument mainDocument; - private static TestDocument dependentDocument; - private static TestDocument mainDocument_before_commit; - private static TestDocument dependentDocument_before_commit; - Establish context = () => - - { - CreateConnection(); - database.DropCollection(_mainCollectionName); - database.DropCollection(_dependentCollectionName); - _mainCollection.InsertOne(TestDocument.DummyData2()); - _dependentCollection.InsertOne(TestDocument.DummyData2()); - - }; - - private Because of = () => - { - var filter = Builders.Filter.Where(x => x.IntTest == 23); - var update = Builders.Update.Inc(i => i.IntTest, 10); - - using (var sessionHandle = client.StartSession()) - { - try - { - var i = 0; - while (i < 2) - { - try - { - i++; - sessionHandle.StartTransaction(new TransactionOptions( - readConcern: ReadConcern.Local, - writeConcern: WriteConcern.W1)); - try - { - var first = _mainCollection.UpdateOne(sessionHandle, filter, update); - var second = _dependentCollection.UpdateOne(sessionHandle, filter, update); - mainDocument_before_commit = _mainCollection.FindSync(sessionHandle, Builders.Filter.Empty).ToList().FirstOrDefault(); - dependentDocument_before_commit = _dependentCollection.FindSync(sessionHandle, Builders.Filter.Empty).ToList().FirstOrDefault(); - } - catch (Exception) - { - sessionHandle.AbortTransaction(); - throw; - } - - //Throw exception and do not commit - throw new ApplicationException(); - } - catch (MongoException e) - { - if (e.HasErrorLabel("TransientTransactionError")) - continue; - throw; - } - - } - } - catch (Exception) - { - - } - } - - mainDocument = _mainCollection.FindSync(Builders.Filter.Empty).FirstOrDefault(); - dependentDocument = _dependentCollection.FindSync(Builders.Filter.Empty).FirstOrDefault(); - }; - - It main_should_be_still_23_after_aborting = () => mainDocument.IntTest.Should().Be(23); - It dependent_should_be_still_23_after_aborting = () => dependentDocument.IntTest.Should().Be(23); - It main_should_be_33_before_aborting = () => mainDocument_before_commit.IntTest.Should().Be(33); - It dependent_should_be_33_before_aborting = () => dependentDocument_before_commit.IntTest.Should().Be(33); - Cleanup cleanup = () => _runner.Dispose(); - } - - [Subject("Runner Transaction Test")] - public class when_replica_set_not_ready_before_timeout_expires : MongoTransactionTest - { - private static Exception exception; - - Because of = () => exception = Catch.Exception(() => CreateConnection(0)); - - // this passes on Windows (TimeoutException as expected) - // but breaks on my Mac (MongoDB.Driver.MongoCommandException: Command replSetInitiate failed: already initialized.) - It should_throw_timeout_exception = () => { - Console.WriteLine(exception.ToString()); - exception.Should().BeOfType(); - }; - } -} diff --git a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/TestDocument.cs b/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/TestDocument.cs deleted file mode 100644 index 34b54eee..00000000 --- a/Mongo2Go-4.1.0/src/Mongo2GoTests/Runner/TestDocument.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; -using MongoDB.Bson; -using MongoDB.Bson.Serialization.Attributes; - -namespace Mongo2GoTests.Runner -{ - public class TestDocument - { - [BsonId] - [BsonRepresentation(BsonType.ObjectId)] - public string Id { get; set; } - - public string StringTest { get; set; } - - public int IntTest { get; set; } - - [BsonDateTimeOptions(Kind = DateTimeKind.Local)] - public DateTime? DateTest { get; set; } - - public List ListTest { get; set; } - - public static TestDocument DummyData1() - { - return new TestDocument - { - StringTest = "Hello World", - IntTest = 42, - DateTest = new DateTime(1984, 09, 30, 6, 6, 6, 171, DateTimeKind.Utc).ToLocalTime(), - ListTest = new List {"I", "am", "a", "list", "of", "strings"} - }; - } - - public static TestDocument DummyData2() - { - return new TestDocument - { - StringTest = "Foo", - IntTest = 23, - }; - } - - public static TestDocument DummyData3() - { - return new TestDocument - { - StringTest = "Bar", - IntTest = 77, - }; - } - - } -} diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/ArchiveExtractor.cs b/Mongo2Go-4.1.0/src/MongoDownloader/ArchiveExtractor.cs deleted file mode 100644 index ee0ed755..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/ArchiveExtractor.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using ByteSizeLib; -using Espresso3389.HttpStream; -using HttpProgress; -using ICSharpCode.SharpZipLib.GZip; -using ICSharpCode.SharpZipLib.Tar; -using ICSharpCode.SharpZipLib.Zip; - -namespace MongoDownloader -{ - internal class ArchiveExtractor - { - private static readonly int CachePageSize = Convert.ToInt32(ByteSize.FromMebiBytes(4).Bytes); - - private readonly Options _options; - private readonly BinaryStripper? _binaryStripper; - - public ArchiveExtractor(Options options, BinaryStripper? binaryStripper) - { - _options = options ?? throw new ArgumentNullException(nameof(options)); - _binaryStripper = binaryStripper; - } - - public async Task>> DownloadExtractZipArchiveAsync(Download download, DirectoryInfo extractDirectory, ArchiveProgress progress, CancellationToken cancellationToken) - { - var bytesTransferred = 0L; - using var headResponse = await _options.HttpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, download.Archive.Url), cancellationToken); - var contentLength = headResponse.Content.Headers.ContentLength ?? 0; - var cacheFile = new FileInfo(Path.Combine(_options.CacheDirectory.FullName, download.Archive.Url.Segments.Last())); - await using var cacheStream = new FileStream(cacheFile.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - var stopwatch = Stopwatch.StartNew(); - await using var httpStream = new HttpStream(download.Archive.Url, cacheStream, ownStream: false, CachePageSize, cached: null); - httpStream.RangeDownloaded += (_, args) => - { - bytesTransferred += args.Length; - progress.Report(new CopyProgress(stopwatch.Elapsed, 0, bytesTransferred, contentLength)); - }; - using var zipFile = new ZipFile(httpStream); - var binaryRegex = _options.Binaries[(download.Product, download.Platform)]; - var licenseRegex = _options.Licenses[(download.Product, download.Platform)]; - var stripTasks = new List>(); - foreach (var entry in zipFile.Cast().Where(e => e.IsFile)) - { - var nameParts = entry.Name.Split('\\', '/').Skip(1).ToList(); - var zipEntryPath = string.Join('/', nameParts); - var isBinaryFile = binaryRegex.IsMatch(zipEntryPath); - var isLicenseFile = licenseRegex.IsMatch(zipEntryPath); - if (isBinaryFile || isLicenseFile) - { - var destinationPathParts = isLicenseFile ? nameParts.Prepend(ProductDirectoryName(download.Product)) : nameParts; - var destinationFile = new FileInfo(Path.Combine(destinationPathParts.Prepend(extractDirectory.FullName).ToArray())); - destinationFile.Directory?.Create(); - await using var destinationStream = destinationFile.OpenWrite(); - await using var inputStream = zipFile.GetInputStream(entry); - await inputStream.CopyToAsync(destinationStream, cancellationToken); - if (isBinaryFile && _binaryStripper is not null) - { - stripTasks.Add(_binaryStripper.StripAsync(destinationFile, cancellationToken)); - } - } - } - progress.Report(new CopyProgress(stopwatch.Elapsed, 0, bytesTransferred, bytesTransferred)); - return stripTasks; - } - - public IEnumerable> ExtractArchive(Download download, FileInfo archive, DirectoryInfo extractDirectory, CancellationToken cancellationToken) - { - switch (Path.GetExtension(archive.Name)) - { - case ".tgz": - return ExtractTarGzipArchive(download, archive, extractDirectory, cancellationToken); - default: - throw new NotSupportedException($"Only .tgz archives are currently supported. \"{archive.FullName}\" can not be extracted."); - } - } - - private IEnumerable> ExtractTarGzipArchive(Download download, FileInfo archive, DirectoryInfo extractDirectory, CancellationToken cancellationToken) - { - // See https://github.com/icsharpcode/SharpZipLib/wiki/GZip-and-Tar-Samples#-simple-full-extract-from-a-tgz-targz - using var archiveStream = archive.OpenRead(); - using var gzipStream = new GZipInputStream(archiveStream); - using var tarArchive = TarArchive.CreateInputTarArchive(gzipStream, Encoding.UTF8); - var extractedFileNames = new List(); - tarArchive.ProgressMessageEvent += (_, entry, _) => - { - cancellationToken.ThrowIfCancellationRequested(); - extractedFileNames.Add(entry.Name); - }; - tarArchive.ExtractContents(extractDirectory.FullName); - return CleanupExtractedFiles(download, extractDirectory, extractedFileNames); - } - - private IEnumerable> CleanupExtractedFiles(Download download, DirectoryInfo extractDirectory, IEnumerable extractedFileNames) - { - var rootDirectoryToDelete = new HashSet(); - var binaryRegex = _options.Binaries[(download.Product, download.Platform)]; - var licenseRegex = _options.Licenses[(download.Product, download.Platform)]; - var stripTasks = new List>(); - foreach (var extractedFileName in extractedFileNames.Select(e => e.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar))) - { - var extractedFile = new FileInfo(Path.Combine(extractDirectory.FullName, extractedFileName)); - var parts = extractedFileName.Split(Path.DirectorySeparatorChar); - var entryFileName = string.Join("/", parts.Skip(1)); - rootDirectoryToDelete.Add(parts[0]); - var isBinaryFile = binaryRegex.IsMatch(entryFileName); - var isLicenseFile = licenseRegex.IsMatch(entryFileName); - if (!(isBinaryFile || isLicenseFile)) - { - extractedFile.Delete(); - } - else - { - var destinationPathParts = parts.Skip(1); - if (isLicenseFile) - { - destinationPathParts = destinationPathParts.Prepend(ProductDirectoryName(download.Product)); - } - var destinationFile = new FileInfo(Path.Combine(destinationPathParts.Prepend(extractDirectory.FullName).ToArray())); - destinationFile.Directory?.Create(); - extractedFile.MoveTo(destinationFile.FullName); - if (isBinaryFile && _binaryStripper is not null) - { - stripTasks.Add(_binaryStripper.StripAsync(destinationFile)); - } - } - } - var rootArchiveDirectory = new DirectoryInfo(Path.Combine(extractDirectory.FullName, rootDirectoryToDelete.Single())); - var binDirectory = new DirectoryInfo(Path.Combine(rootArchiveDirectory.FullName, "bin")); - binDirectory.Delete(recursive: false); - rootArchiveDirectory.Delete(recursive: false); - return stripTasks; - } - - private static string ProductDirectoryName(Product product) - { - return product switch - { - Product.CommunityServer => "community-server", - Product.DatabaseTools => "database-tools", - _ => throw new ArgumentOutOfRangeException(nameof(product), product, null) - }; - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/ArchiveProgress.cs b/Mongo2Go-4.1.0/src/MongoDownloader/ArchiveProgress.cs deleted file mode 100644 index df127bab..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/ArchiveProgress.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ByteSizeLib; -using HttpProgress; -using Spectre.Console; - -namespace MongoDownloader -{ - public class ArchiveProgress : IProgress - { - private readonly ProgressTask _archiveProgress; - private readonly ProgressTask _globalProgress; - private readonly IEnumerable _allArchiveProgresses; - private readonly Download _download; - private readonly string _completedDescription; - - public ArchiveProgress(ProgressTask archiveProgress, ProgressTask globalProgress, IEnumerable allArchiveProgresses, Download download, string completedDescription) - { - _archiveProgress = archiveProgress ?? throw new ArgumentNullException(nameof(archiveProgress)); - _globalProgress = globalProgress ?? throw new ArgumentNullException(nameof(globalProgress)); - _allArchiveProgresses = allArchiveProgresses ?? throw new ArgumentNullException(nameof(allArchiveProgresses)); - _download = download ?? throw new ArgumentNullException(nameof(download)); - _completedDescription = completedDescription ?? throw new ArgumentNullException(nameof(completedDescription)); - } - - public void Report(ICopyProgress progress) - { - _archiveProgress.Value = progress.BytesTransferred; - _archiveProgress.MaxValue = progress.ExpectedBytes; - - string text; - bool isIndeterminate; - if (progress.BytesTransferred < progress.ExpectedBytes) - { - var speed = ByteSize.FromBytes(progress.BytesTransferred / progress.TransferTime.TotalSeconds); - text = $"Downloading {_download} from {_download.Archive.Url} at {speed:0.0}/s"; - isIndeterminate = false; - } - else - { - text = $"Downloaded {_download}"; - isIndeterminate = true; - // Cheat by subtracting 1 so that the progress stays at 99% in indeterminate mode for - // remaining tasks (stripping) to complete with an indeterminate progress bar - _archiveProgress.Value = progress.BytesTransferred - 1; - } - Report(text, isIndeterminate); - - lock (_globalProgress) - { - _globalProgress.Value = _allArchiveProgresses.Sum(e => e.Value); - _globalProgress.MaxValue = _allArchiveProgresses.Sum(e => e.MaxValue); - } - } - - public void Report(string action) - { - Report(action, isIndeterminate: true); - } - - public void ReportCompleted(ByteSize strippedSize) - { - _archiveProgress.Value = _archiveProgress.MaxValue; - - lock (_globalProgress) - { - if (_allArchiveProgresses.All(e => e.IsFinished)) - { - _globalProgress.Description = _completedDescription; - _globalProgress.Value = _globalProgress.MaxValue; - } - } - - var saved = strippedSize.Bytes > 0 ? $" (saved {strippedSize:#.#} by stripping)" : ""; - Report($"Extracted {_download}{saved}", isIndeterminate: false); - } - - private void Report(string description, bool isIndeterminate) - { - _archiveProgress.Description = description; - _archiveProgress.IsIndeterminate = isIndeterminate; - lock (_globalProgress) - { - _globalProgress.IsIndeterminate = _allArchiveProgresses.All(e => e.IsFinished || e.IsIndeterminate); - } - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/BinaryStripper.cs b/Mongo2Go-4.1.0/src/MongoDownloader/BinaryStripper.cs deleted file mode 100644 index a6ccb618..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/BinaryStripper.cs +++ /dev/null @@ -1,92 +0,0 @@ -using System; -using System.ComponentModel; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using ByteSizeLib; -using CliWrap; - -namespace MongoDownloader -{ - public class BinaryStripper - { - private const string LlvmStripToolName = "llvm-strip"; - - private readonly string _llvmStripPath; - - private BinaryStripper(string llvmStripPath) - { - _llvmStripPath = llvmStripPath ?? throw new ArgumentNullException(nameof(llvmStripPath)); - } - - public static async Task CreateAsync(CancellationToken cancellationToken) - { - var llvmStripPath = await GetLlvmStripPathAsync(cancellationToken); - return new BinaryStripper(llvmStripPath); - } - - public async Task StripAsync(FileInfo executable, CancellationToken cancellationToken = default) - { - var sizeBefore = ByteSize.FromBytes(executable.Length); - await Cli.Wrap(_llvmStripPath).WithArguments(executable.FullName).ExecuteAsync(cancellationToken); - executable.Refresh(); - var sizeAfter = ByteSize.FromBytes(executable.Length); - return sizeBefore - sizeAfter; - } - - private static async Task GetLlvmStripPathAsync(CancellationToken cancellationToken) - { - try - { - await Cli.Wrap(LlvmStripToolName).WithArguments("--version").ExecuteAsync(cancellationToken); - // llvm-strip is on the PATH - return LlvmStripToolName; - } - catch (Win32Exception exception) when (exception.NativeErrorCode == 2) - { - // llvm-strip is NOT in the PATH, let's search with homebrew - var llvmStripToolPath = await TryGetLlvmStripPathWithHomebrew(); - - if (llvmStripToolPath != null) - { - return llvmStripToolPath; - } - - throw new FileNotFoundException($"The \"{LlvmStripToolName}\" tool was not found."); - } - } - - private static async Task TryGetLlvmStripPathWithHomebrew() - { - if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return null; - } - - string? llvmStripToolPath = null; - try - { - await Cli.Wrap("brew") - // don't validate exit code, if `brew list llvm` fails it's because the llvm formula is not installed - .WithValidation(CommandResultValidation.None) - .WithArguments(new[] {"list", "llvm"}) - .WithStandardOutputPipe(PipeTarget.ToDelegate(line => - { - if (llvmStripToolPath == null && line.EndsWith(LlvmStripToolName)) - { - llvmStripToolPath = line; - } - })) - .ExecuteAsync(); - } - catch (Win32Exception exception) when (exception.NativeErrorCode == 2) - { - // brew is not installed - return null; - } - - return llvmStripToolPath; - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/DataModel.cs b/Mongo2Go-4.1.0/src/MongoDownloader/DataModel.cs deleted file mode 100644 index 26366c38..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/DataModel.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text.Json.Serialization; - -// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global -// ReSharper disable ClassNeverInstantiated.Global -// ReSharper disable CollectionNeverUpdated.Global - -namespace MongoDownloader -{ - public enum Platform - { - Linux, - // ReSharper disable once InconsistentNaming - macOS, - Windows, - } - - public enum Product - { - CommunityServer, - DatabaseTools, - } - - /// - /// The root object of the JSON describing the available releases. - /// - public class Release - { - [JsonPropertyName("versions")] - public List Versions { get; set; } = new(); - } - - public class Version - { - [JsonPropertyName("version")] - public string Number { get; set; } = ""; - - [JsonPropertyName("production_release")] - public bool Production { get; set; } = false; - - [JsonPropertyName("downloads")] - public List Downloads { get; set; } = new(); - } - - public class Download - { - /// - /// Used to identify the platform for the Community Server archives - /// - [JsonPropertyName("target")] - public string Target { get; set; } = ""; - - /// - /// Used to identify the platform for the Database Tools archives - /// - [JsonPropertyName("name")] - public string Name { get; set; } = ""; - - [JsonPropertyName("arch")] - public string Arch { get; set; } = ""; - - [JsonPropertyName("edition")] - public string Edition { get; set; } = ""; - - [JsonPropertyName("archive")] - public Archive Archive { get; set; } = new(); - - public Product Product { get; set; } - - public Platform Platform { get; set; } - - public Architecture Architecture { get; set; } - - public override string ToString() => $"{Product} for {Platform}/{Architecture.ToString().ToLowerInvariant()}"; - } - - public class Archive - { - [JsonPropertyName("url")] - public Uri Url { get; set; } = default!; - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/MongoDbDownloader.cs b/Mongo2Go-4.1.0/src/MongoDownloader/MongoDbDownloader.cs deleted file mode 100644 index a126b912..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/MongoDbDownloader.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net.Http.Json; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using ByteSizeLib; -using HttpProgress; -using Spectre.Console; - -namespace MongoDownloader -{ - internal class MongoDbDownloader - { - private readonly ArchiveExtractor _extractor; - private readonly Options _options; - - public MongoDbDownloader(ArchiveExtractor extractor, Options options) - { - _extractor = extractor ?? throw new ArgumentNullException(nameof(extractor)); - _options = options ?? throw new ArgumentNullException(nameof(options)); - } - - public async Task RunAsync(DirectoryInfo toolsDirectory, CancellationToken cancellationToken) - { - var strippedSize = await AnsiConsole - .Progress() - .Columns( - new ProgressBarColumn(), - new PercentageColumn(), - new RemainingTimeColumn(), - new DownloadedColumn(), - new TaskDescriptionColumn { Alignment = Justify.Left } - ) - .StartAsync(async context => await RunAsync(context, toolsDirectory, cancellationToken)); - - return strippedSize; - } - - private async Task RunAsync(ProgressContext context, DirectoryInfo toolsDirectory, CancellationToken cancellationToken) - { - const double initialMaxValue = double.Epsilon; - var globalProgress = context.AddTask("Downloading MongoDB", maxValue: initialMaxValue); - - var (communityServerVersion, communityServerDownloads) = await GetCommunityServerDownloadsAsync(cancellationToken); - globalProgress.Description = $"Downloading MongoDB Community Server {communityServerVersion.Number}"; - - var (databaseToolsVersion, databaseToolsDownloads) = await GetDatabaseToolsDownloadsAsync(cancellationToken); - globalProgress.Description = $"Downloading MongoDB Community Server {communityServerVersion.Number} and Database Tools {databaseToolsVersion.Number}"; - - var tasks = new List>(); - var allArchiveProgresses = new List(); - foreach (var download in communityServerDownloads.Concat(databaseToolsDownloads)) - { - var archiveProgress = context.AddTask($"Downloading {download} from {download.Archive.Url}", maxValue: initialMaxValue); - var directoryName = $"mongodb-{download.Platform.ToString().ToLowerInvariant()}-{download.Architecture.ToString().ToLowerInvariant()}-{communityServerVersion.Number}-database-tools-{databaseToolsVersion.Number}"; - var extractDirectory = new DirectoryInfo(Path.Combine(toolsDirectory.FullName, directoryName)); - allArchiveProgresses.Add(archiveProgress); - var progress = new ArchiveProgress(archiveProgress, globalProgress, allArchiveProgresses, download, $"✅ Downloaded and extracted MongoDB Community Server {communityServerVersion.Number} and Database Tools {databaseToolsVersion.Number} into {new Uri(toolsDirectory.FullName).AbsoluteUri}"); - tasks.Add(ProcessArchiveAsync(download, extractDirectory, progress, cancellationToken)); - } - var strippedSizes = await Task.WhenAll(tasks); - return strippedSizes.Aggregate(new ByteSize(0), (current, strippedSize) => current + strippedSize); - } - - private async Task ProcessArchiveAsync(Download download, DirectoryInfo extractDirectory, ArchiveProgress progress, CancellationToken cancellationToken) - { - IEnumerable> stripTasks; - var archiveExtension = Path.GetExtension(download.Archive.Url.AbsolutePath); - if (archiveExtension == ".zip") - { - stripTasks = await _extractor.DownloadExtractZipArchiveAsync(download, extractDirectory, progress, cancellationToken); - } - else - { - var archiveFileInfo = await DownloadArchiveAsync(download.Archive, progress, cancellationToken); - stripTasks = _extractor.ExtractArchive(download, archiveFileInfo, extractDirectory, cancellationToken); - } - progress.Report("Stripping binaries"); - var completedStripTasks = await Task.WhenAll(stripTasks); - var totalStrippedSize = completedStripTasks.Aggregate(new ByteSize(0), (current, strippedSize) => current + strippedSize); - progress.ReportCompleted(totalStrippedSize); - return totalStrippedSize; - } - - private async Task DownloadArchiveAsync(Archive archive, IProgress progress, CancellationToken cancellationToken) - { - _options.CacheDirectory.Create(); - var destinationFile = new FileInfo(Path.Combine(_options.CacheDirectory.FullName, archive.Url.Segments.Last())); - var useCache = bool.TryParse(Environment.GetEnvironmentVariable("MONGO2GO_DOWNLOADER_USE_CACHED_FILE") ?? "", out var useCachedFile) && useCachedFile; - if (useCache && destinationFile.Exists) - { - progress.Report(new CopyProgress(TimeSpan.Zero, 0, 1, 1)); - return destinationFile; - } - await using var destinationStream = destinationFile.OpenWrite(); - await _options.HttpClient.GetAsync(archive.Url.AbsoluteUri, destinationStream, progress, cancellationToken); - return destinationFile; - } - - private async Task<(Version version, IEnumerable downloads)> GetCommunityServerDownloadsAsync(CancellationToken cancellationToken) - { - var release = await _options.HttpClient.GetFromJsonAsync(_options.CommunityServerUrl, cancellationToken) ?? throw new InvalidOperationException($"Failed to deserialize {nameof(Release)}"); - var version = release.Versions.FirstOrDefault(e => e.Production) ?? throw new InvalidOperationException("No Community Server production version was found"); - var downloads = Enum.GetValues().SelectMany(platform => GetDownloads(platform, Product.CommunityServer, version, _options, _options.Edition)); - return (version, downloads); - } - - private async Task<(Version version, IEnumerable downloads)> GetDatabaseToolsDownloadsAsync(CancellationToken cancellationToken) - { - var release = await _options.HttpClient.GetFromJsonAsync(_options.DatabaseToolsUrl, cancellationToken) ?? throw new InvalidOperationException($"Failed to deserialize {nameof(Release)}"); - var version = release.Versions.FirstOrDefault() ?? throw new InvalidOperationException("No Database Tools version was found"); - var downloads = Enum.GetValues().SelectMany(platform => GetDownloads(platform, Product.DatabaseTools, version, _options)); - return (version, downloads); - } - - private static IEnumerable GetDownloads(Platform platform, Product product, Version version, Options options, Regex? editionRegex = null) - { - var platformRegex = options.PlatformIdentifiers[platform]; - Func platformPredicate = product switch - { - Product.CommunityServer => download => platformRegex.IsMatch(download.Target), - Product.DatabaseTools => download => platformRegex.IsMatch(download.Name), - _ => throw new ArgumentOutOfRangeException(nameof(product), product, $"The value of argument '{nameof(product)}' ({product}) is invalid for enum type '{nameof(Product)}'.") - }; - - foreach (var architecture in options.Architectures[platform]) - { - var architectureRegex = options.ArchitectureIdentifiers[architecture]; - var matchingDownloads = version.Downloads - .Where(platformPredicate) - .Where(e => architectureRegex.IsMatch(e.Arch)) - .Where(e => editionRegex?.IsMatch(e.Edition) ?? true) - .ToList(); - - if (matchingDownloads.Count == 0) - { - var downloads = version.Downloads.OrderBy(e => e.Target).ThenBy(e => e.Arch); - var messages = Enumerable.Empty() - .Append($"Download not found for {platform}/{architecture}.") - .Append($" Available downloads for {product} {version.Number}:") - .Concat(downloads.Select(e => $" - {e.Target}/{e.Arch} ({e.Edition})")); - throw new InvalidOperationException(string.Join(Environment.NewLine, messages)); - } - - if (matchingDownloads.Count > 1) - { - throw new InvalidOperationException($"Found {matchingDownloads.Count} downloads for {platform}/{architecture} but expected to find only one."); - } - - var download = matchingDownloads[0]; - download.Platform = platform; - download.Architecture = architecture; - download.Product = product; - - yield return download; - } - } - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/MongoDownloader.csproj b/Mongo2Go-4.1.0/src/MongoDownloader/MongoDownloader.csproj deleted file mode 100644 index cb8a14ed..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/MongoDownloader.csproj +++ /dev/null @@ -1,21 +0,0 @@ - - - - Exe - net8.0 - enable - false - - - - - - - - - - - - - - diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/Options.cs b/Mongo2Go-4.1.0/src/MongoDownloader/Options.cs deleted file mode 100644 index ab1d42b1..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/Options.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Runtime.InteropServices; -using System.Text.RegularExpressions; - -namespace MongoDownloader -{ - internal class Options - { - /// - /// The instance used to fetch data over HTTP. - /// - public HttpClient HttpClient { get; init; } = new(); - - /// - /// The URL of the MongoDB Community Server download information JSON. - /// - public string CommunityServerUrl { get; init; } = "https://s3.amazonaws.com/downloads.mongodb.org/current.json"; - - /// - /// The URL of the MongoDB Database Tools download information JSON. - /// - public string DatabaseToolsUrl { get; init; } = "https://s3.amazonaws.com/downloads.mongodb.org/tools/db/release.json"; - - /// - /// The directory to store the downloaded archive files. - /// - public DirectoryInfo CacheDirectory { get; init; } = new(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.InternetCache), nameof(MongoDownloader))); - - /// - /// The architectures to download for a given platform. - /// - public IReadOnlyDictionary> Architectures { get; init; } = new Dictionary> - { - [Platform.Linux] = new[] { Architecture.Arm64, Architecture.X64 }, - [Platform.macOS] = new[] { Architecture.X64 }, - [Platform.Windows] = new[] { Architecture.X64 }, - }; - - /// - /// The edition of the archive to download. - /// - /// macOS and Windows use base and Linux uses targeted for the community edition - public Regex Edition { get; init; } = new(@"base|targeted"); - - /// - /// The regular expressions used to identify platform-specific archives to download. - /// - public IReadOnlyDictionary PlatformIdentifiers { get; init; } = new Dictionary - { - [Platform.Linux] = new(@"ubuntu2004", RegexOptions.IgnoreCase), - [Platform.macOS] = new(@"macOS", RegexOptions.IgnoreCase), - [Platform.Windows] = new(@"windows", RegexOptions.IgnoreCase), - }; - - /// - /// The regular expressions used to identify architectures to download. - /// - public IReadOnlyDictionary ArchitectureIdentifiers { get; init; } = new Dictionary - { - [Architecture.Arm64] = new("arm64|aarch64", RegexOptions.IgnoreCase), - [Architecture.X64] = new("x86_64", RegexOptions.IgnoreCase), - }; - - /// - /// A dictionary describing how to match MongoDB binaries inside the zip archives. - /// - /// The key is a tuple with the / and the - /// value is a regular expressions to match against the zip file name entry. - /// - public IReadOnlyDictionary<(Product, Platform), Regex> Binaries { get; init; } = new Dictionary<(Product, Platform), Regex> - { - [(Product.CommunityServer, Platform.Linux)] = new(@"bin/mongod"), - [(Product.CommunityServer, Platform.macOS)] = new(@"bin/mongod"), - [(Product.CommunityServer, Platform.Windows)] = new(@"bin/mongod\.exe"), - [(Product.DatabaseTools, Platform.Linux)] = new(@"bin/(mongoexport|mongoimport)"), - [(Product.DatabaseTools, Platform.macOS)] = new(@"bin/(mongoexport|mongoimport)"), - [(Product.DatabaseTools, Platform.Windows)] = new(@"bin/(mongoexport|mongoimport)\.exe"), - }; - - /// - /// A dictionary describing how to match licence files inside the zip archives. - /// - /// The key is a tuple with the / and the - /// value is a regular expressions to match against the zip file name entry. - /// - public IReadOnlyDictionary<(Product, Platform), Regex> Licenses { get; init; } = new Dictionary<(Product, Platform), Regex> - { - // The regular expression matches anything at the zip top level, i.e. does not contain any slash (/) character - [(Product.CommunityServer, Platform.Linux)] = new(@"^[^/]+$"), - [(Product.CommunityServer, Platform.macOS)] = new(@"^[^/]+$"), - [(Product.CommunityServer, Platform.Windows)] = new(@"^[^/]+$"), - [(Product.DatabaseTools, Platform.Linux)] = new(@"^[^/]+$"), - [(Product.DatabaseTools, Platform.macOS)] = new(@"^[^/]+$"), - [(Product.DatabaseTools, Platform.Windows)] = new(@"^[^/]+$"), - }; - } -} \ No newline at end of file diff --git a/Mongo2Go-4.1.0/src/MongoDownloader/Program.cs b/Mongo2Go-4.1.0/src/MongoDownloader/Program.cs deleted file mode 100644 index 6fcb3a23..00000000 --- a/Mongo2Go-4.1.0/src/MongoDownloader/Program.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using Spectre.Console; - -namespace MongoDownloader -{ - internal static class Program - { - private static async Task Main(string[] args) - { - try - { - var toolsDirectory = GetToolsDirectory(); - - foreach (DirectoryInfo dir in toolsDirectory.EnumerateDirectories()) - { - dir.Delete(true); - } - - var cancellationTokenSource = new CancellationTokenSource(); - Console.CancelKeyPress += (_, eventArgs) => - { - // Try to cancel gracefully the first time, then abort the process the second time Ctrl+C is pressed - eventArgs.Cancel = !cancellationTokenSource.IsCancellationRequested; - cancellationTokenSource.Cancel(); - }; - var options = new Options(); - var performStrip = args.All(e => e != "--no-strip"); - var binaryStripper = performStrip ? await GetBinaryStripperAsync(cancellationTokenSource.Token) : null; - var archiveExtractor = new ArchiveExtractor(options, binaryStripper); - var downloader = new MongoDbDownloader(archiveExtractor, options); - var strippedSize = await downloader.RunAsync(toolsDirectory, cancellationTokenSource.Token); - if (performStrip) - { - AnsiConsole.WriteLine($"Saved {strippedSize:#.#} by stripping executables"); - } - return 0; - } - catch (Exception exception) - { - if (exception is not OperationCanceledException) - { - AnsiConsole.WriteException(exception, ExceptionFormats.ShortenPaths); - } - return 1; - } - } - - private static DirectoryInfo GetToolsDirectory() - { - for (var directory = new DirectoryInfo("."); directory != null; directory = directory.Parent) - { - var toolsDirectory = directory.GetDirectories("tools", SearchOption.TopDirectoryOnly).SingleOrDefault(); - if (toolsDirectory?.Exists ?? false) - { - return toolsDirectory; - } - } - throw new InvalidOperationException("The tools directory was not found"); - } - - private static async Task GetBinaryStripperAsync(CancellationToken cancellationToken) - { - try - { - return await BinaryStripper.CreateAsync(cancellationToken); - } - catch (FileNotFoundException exception) - { - string installCommand; - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - installCommand = "brew install llvm"; - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - installCommand = "scoop install llvm"; - else - installCommand = "apt-get install llvm"; - - throw new Exception($"{exception.Message} Either install llvm with `{installCommand}` or run MongoDownloader with the --no-strip option to skip binary stripping.", exception); - } - } - } -} diff --git a/Mongo2Go-4.1.0/src/mongo2go_200_200.png b/Mongo2Go-4.1.0/src/mongo2go_200_200.png deleted file mode 100644 index 23750b60b217997121d919c0489c75e17dcc3b20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21563 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¾%|676PK0PXi4Y#L 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

2nQN!*utOo}o6rJ;Veeoy{V%+5 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

4I_OOo4&V$0MxG12GYD;0mjekd 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�*ib*0D*8@-#dCM^D!e*9mLRa}jGp0A$& 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 rTY7=)(|9>ktr&jF6JR! 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 z z#9`ztPTCEiVpqq+W`LVu^n z|M9#3^-te@_uap43cwrv{j2hSxjuhq1Moln^Z)pppFP3S_Ft|qWI=$zJL@9Z22Y9v z+`KdH@<`ot;2k?kdSKp-GzjF?Jd=M*`DlA9uD9orlz{sk=HHMl#_52yPdzLlLEv8I zM>t5sWmz~d&iK;PDgCV^<{X)!?6lj;f@qWWU|49pl84+} zhiA7l{u!&gj;ExDHaG$5n0;SaXo(N6&ZT>9 z80WdDG^_wBNbhM^`82+dmy^db?aSM&3=b{7!ptz>tV&9ONbomO*XH~HejaZkW>zB9 zS2uY-Ur0uYubE(-ZYvs|$zWeU$-$R4{p!!Sk75#nm z=+Wcu)!=B{>2xOWq=W8!GVczs#vTa`^Ez(K$NkQ#6I_Y98@EAw7wW>y1_sR!Cy>+;eC9S* zuje?vFww|LQ{`{A;u!ZJ1Lxr#@Qrq$mJIvH;m*$U9=H$tz_-~uJME}5nM_Be9`^qTmb z!K?rSFXCraT1FALAThNTI_|?8kKBY6To<{-klzXHTjz0>hg(Wgj(NChH4M{I@9%$q z`#--+*Vnfj1H94Sze@P+voA6Q{&JnlldnJEr~cRa!~b9Zff0;ff&lS|6Noiw^0B@x-4Tt>RT(9VYIU35*06wA=VE}r zj@LzJLp}>b`p%B7My3mG_{tkC&<~u?!kCcdqgU&!iA;tY;&@&Mw%h88LwKr4-Ib^Z zsJ8t@se$Tidrum{4KjfF6#&vId1!)GcBn7o6m`g!UHRCV{X4Smt;aGVp&Y%cR3r{Lb%T^l(kiI?yyxHg=XOeg$STgJYeG9W&~;!%Qn3!;Xxpdy-d3g? z-=uxOP4BvJP-%|r#%1Nr`R(!fonb+(N~PGkZ8g)98xLVPKSqQ|#kpRH={Q<`ui8JPbQ!I{g+>*2#BxV*?{)X-`!bX|L!0EC+fCpCt&zZp&wwy63Xl|SPCidNNS@m}(^5()v>$Pe?SCSMAlRSqb9v>dIdf_&Z z5WUXPXf$iH3!)|D2knEH4myq*h4Bh=Kl@`myxAlLVmj5b?~5}~e8n+Gy%>%Zo_8NQ ztNJ@g@ZbjC!SOz+4pmF_*BRI*1NWlgfG1J5p}&`$g{)m@RX8`VX31Q*SFf5#*kQ*# zYNB+*R8y@3I|I?*A&nbl-OJ z;7%Ie=|TSwH7+g$ib^U~@J81Q_JJe3gCfy^7w3X_AeX+cN%S}nl6oLD5T1kVe#J#6 zk(ksqlnF&piAWn;9(s5N2R*pjJ{n2RO(^zT>-&A%tz}ZFN>b-kox6YC)!FWR?wD$` zvi9#=YyA@9!bn1eVI;5u>}>!ZSLvL>c4fJT69ob!Rcp*l!#z93d>)e(_g!icrV#H7 zG7*atm5F{BdgJW_KAU(IKZC9L)?j`b4%DW)6s+>_md1GlVdACVin&nZEr+V?r$+c8Mq5)TB{%`VCopCM-e%NcF?iZ z-Xz(1yi8t9U5qFnHs}KvEt$OTcF~k7WJ^DDuZ~^jnt5%-S4YYIXp7pHUPJKrXU;i`Szdwi^AW(f038z z$Efd)fIHYcV?F=wSZ6;lI$dcZEamS+2Rz)jlFyF7g2`2Ft?=P1nT8=b5H{x}6P8N9 zB-`$-;rvcT&Aw0yGu`=3y&)P~Q{i|#<$-&1_^uv!mB*Y$-_@hP>h zaNDMumf_NClIRv(*gh~(2kX>`I%d9++m3p|Wo3<;7dNLS-ok`9>zY%#Un1nNFyI4L zLvd;Xvu4j5qAXTP>qBB>SxANoVskMoh2GFgLx}CqV9nRjN|$N=j!tbba2?N zV$P?K?@ZLkQ#v$Gw~#djWV?ag8vR1Mkuy(YGPlVvuPGxjIGav>xK#DKe+&dCNGl7y z<8W{qf5)C_=v`WH8W0Zt-lCQWwU4g2g?coPze0fLLHHm4B>1ZenuTp9pUM2=?OLh@BvmRU+ zxGd<46f|6Ev-qRJ-@Vrp{LR?-JDUe#dEf}a$dhX}J;C2qvm4hsGj4`bRNM;t5^tYoqgx)cfh2>7en>d%{llwOWw za$5ml&X8BfO3B-mxu1B1Oy7x9qntGk6Rw=lt9X15i;zpz}?^-;?H4oclV)6QJ3 z7{ne5e|LY)_BtiTyj{kM=C!qlyy)bmcn!~u*YKeH+qeJSJ)W+}mFy!tj!wfbeuy0W zb@2CgwYV^M3w6~H+72ev z177F(uRMB({{m|z>p?&ln`K%7%=6&98h@wx@9-ox!CyM#ctm7is?I;m;O{(EZbEIs zHFhS#JpOVO`U$cIdt%cVUB2R)No;J%>M4gCizqr2bY-s^uTF@uy^6DnM?Bzh9EuEW zt%G|_&A-=}PTnm*s}jyK(gDsCfbQxn6~uOq1Kq=%_$HN^{w`O0on$=8E-ym#u~Atx zlJvv1;VCxW1HMIkBTSZ%I*N%Fg)D4%*Nb{&GUH#eX}B{}Od^tnk;K zi%e7||GgpwVpZ_>YW~})+4#$}cFlkF5vwqbznIu5_{%(q>+zS^%VIy&@*UeAIAW!Z zn4og69Ix_xOp`G8n5T+|v zQox*{OHIyVb@e!QL4vJtS@3tpwIQ5(a7O&a8fZN%zI=(VYvJ!!vN6?*$Uud%m5lv* zxs_}cTL!n$VD~F$8oiuhZh;FA%=cIE^qg1eb&$KmYp})Z3q=Ae!FAKOGS7d_z<9d6 zx%#xTAw78*OwZdi>Oy;4ko& z)q##-P2d;qx9x-W4E{=SjWmPzRJTI6B7nK%yuyF?(3K?UO8>Vp%YStqu!X;zEN{<6 z#zQ*=LXLo|Z76t!|Nb<`f8lk-r|fQUR)z9NpI75Al*JSL<#|pPv-%IK*Ws@q@aTk2 zGns+W77v^?Q+-G9SJu>yq@|mJvSPk7svTvWbFF%4?8LVwvw>f5jZW~HBuD@U?Y^^M zC5qIw4Clx{=q{}6f(g@gl{qij&gJDf*)x3cVgUadui4aHgXt^@E{mhTE;!!WYbGxz z7%g*)rKg;*lOH$%*J>6~D{P8!O`VMm_5$NO90TkHUdJ{tozC zwXz=o#^9u~=Y~ggzU?K@GwzvC+g7UV3q#EMBQ!?9TzSF?+;5zQOdhS7FzGMW9DuEY zUn7s_@Ni8Wa471N8YxMKsA0OgfNn}nNPZ*AG$?|3NCr&LoazOW74K0G3E;V&2N84Y#7*@C_P*E|ZPOv&LZ5;YkMVc%Z~yW?g1-%i z{ee)JfU34K*3+Iaj^4%JH2H>Uews_49<3Qc+<~-s8~O(; z6Sz(f9Hu18jAd(91~6Jpi=zWhCdEl#qNMipz;sb-m@p3fCH!(TJG3es*Un>KWm1H=;pns2sZ_*wHEhdlVE`?$0~s*HUmi<_ zLU}{@Z~f2N)yXuBRg3>p3n52^HmC7+@Sir^bNmA*9r5+DoGDS;OXnNb$SmbTbIV0_ z?uKT$_I$K>e@HK0udVOlvqPgEqkdUC%7!X8p{LhNZWvW&vvbz$NA#fO)%PmlJfeO$ zfYRhr^ujuEf}C{cq@g`%o1z?MQE!WDDrGPp6~qHK>g`Y+t<@P!pU^25&=wzDp&@G} zFXAP$3ca*>V^wlZaO90bE8+`;!vSw3pa&9GBOvV;riXrq)%7(1>b=dDL7XJS;TA%UaHu8E+15pKItYIP==;oQYn z2k##JYl(d%UXY}3a7~*D5*Z=A$V-=N_BzDhtellKOpR!E%qyx>-aRwSe6M;V`sQ17 zPyfds|AmrXAT9a~W@vq4EmFqfFsSc*QRlF-;>Snd*k^Sg*o_D}xswk5-g^$j(!=-8 zpa*RTnYSozY=8`VBkR-ikHz)IGcS7xOQR-A$4rx$}yD|a55I9YC0vtp*8;iBNoOhe;2nOtt=2hicACO7kOrK6s^qt5UT_u$9@ zxl(16$q|O|;+R}eWgCF6f(dioaW%Qc9NV~}yNw339jZHe4TEescUjUT;EHSZRo(%k zDVP<6ugA_Sb8UJ%z~N?fkKcVo&8BOD`DzE=$*>?ywNn*$U7v{zlk4z1;3H0UhoKQG z_+2uAj7nWNt`!ScSqwUvfgU$We~e|*l03mohEzkjl1C~TLUJaWDSD*&e}Mmoa{BCO zl*6>)J61LRfB*GcOTN28?6oWH3){`JYw%Z--Z2iOe868^#_9e#_$?-z5AM}6ihSw@r_cUWlPAY+)Ot>#;X-DZ{`845eJMzaP&hJzJrv8N~OCE>)uIX z*y&V(Km}B*2!C82ckw98;noDoAbY2Z5aMpd=z*OkfP_qo83G%@jCTv@$yTa8z#EWI z9W^kXy?O-JT1^adCG;9FCruo2rD04p2DakEohnws`PXG?8`pq>@~$6~emB3bGxuyb zY$X(5W)>xKGLCnU*Z}<9;8fopawAH{-eKwcL{H^C#A5LbaF)l}B-UdEa~32^jT7aG z&^#|G5GjT~WQv>g-!ZEvn_=&@KqLivt2BvbCaE$c5>@nK&b5Dy&)82ZraffBLxw3m z1<>MzZ-4c|2turonfwH+!=X^uhFnC67f*C;00| z{{gk)v>zP&y)ytWOyTdtC+77II97CK7dUEuT#1G)z&HKx1ONWd&wH>KcaTv@v^xav zt*h-hm9%ul>BbSKk*_d^Gn%DOlX;Jx`_H{FtKJK?ZaZO%JsvE-l%?0CdSf zs~qj1gac{=z!Ad{`@bTnxMBUQYxsx`n` z1A((`&1Hd1I~A3@8&ld~65%6etbtQXub8aWIw~{^ibWqGtpR1{0HY)yVh;&t$U2iX zdZc7_wEr@O?nSdHxoOEQTOGk%T^45u^A$CknanD>9#AZhp6cv}*ty-kZD!^A=Z??BAYj#fJee=Ew+i5|c zy8nuJrf6@PccUH_Q@(z)Rjs&!ZwqfM!huyUw5}o?~ix-FcMt)~!4Y$X})ZL|_(jjn* zoa?9y8J$Lo`m#j+^?~fX5sR@V-TqEzprsk0wzgKp@m^&be`{UA-$L*8pZ5$LukxSg z?RvMNauiD{HKG8P+khLZOFR%K$bqOJt2e_m1)UJiIT$hrS)5u-OGolUJee#oDMJJuws z=DpRrA6ZfJZ_$ufcY8mq(vo}Ghrw3-H$ry;g$H2WioO-(O{r$0dfj+ zyTdzw^aD&?28?hy?iv9$hr?2%ihaI<)&TEmJuqd!dz@CJ(U&T-UfTj=Oc9b}05F4o zW&aF{;EDDDYh(hPJ(+&i12>}rwi6+whMEPkTxCoB!1)oQ<^@keb34e+OhwiNI0nVr z)}_?uK`W&v`f`drxu$ybz06G0k93B_rSR7J!S3bUoM8J{RKpwA^t7{#T*p2yrMzhy zg2cGdz`P&r#S_M>*Ch7Jns`I&yra1DMGTu}M!xTgU0%L5&p5@67_B{Sy;0u0j|v66 z-mCX2yyK56pSu$$D8d7+Q~nIzIz~O(~@3qEA|{%QX5#nu@i?5A&1h*BXXt%x#dDuu&#Q zmDDe(j&;pmDQ9*Qg_KsIRbO-7kQ5cf?KKO3jn~9q;lB;+ngM?y{$)~H^A|eefWNDG z%tx5V-=Aji*G_@>X$F6}TgKEb`j90PLh!d(Z|P}7rS6FMOK27R)sYbKY-M}*QmWV; z0%v)e_{koxtofgtR%!$vO=U>n*+!Qzs5Hda;BTpG;V-hzEHu63`FZ>$YUZIg$r69< z3B`KNutNM5ly0<>r~RU(NI*CG%zS%EXT{-Y)G8JsJl;x{?uYmWf??n6sYnpzQS3K3 z{-_Fy>>>0H_W&Ay!~TP2zfTQ+)PAI~m?I~2FXCGMYoE;yk=P)M<@_xE z>Q&5mz-Q+2CtOLc;Su`8Im~!}`_{tW+{Uk4(pTQfnMMhRmo4+2%Ilqb*F}PItF|)! z_>woiL_pa6-w^P(rhi%E4A%4M5+_{|yfnqAp(NWyOU*y@A?FML%7=^N9%2dQAbT5k$wyqa?P+@K~PB)6@L- z@_PJjjL5Hr|6uH##`AQ` zY@wCQl}aj!?cy!+(V;{eZ6ybW`DrTTNqd6hyH;=}0xb}vALBPxV#)&W*U5o!@b|X0 zWcx23&P+iTWEP+0*LQyp2Yey(j#cYOlXtE#t&vk}3pIF$H5RMnGve=eJF)~0WAuMJ z=FMf~I8kU=$f25Y!AA_SIMocEl3ae6Yc zq0+vs9AMl1mT4XyY^g&q)t<$F({T3M`iBN_naD~n@GI#iY+{N9nXvpr9fGZlkjcn0 zDLB;zqR#W*%d7F1Nj>LN^WN?LLpht)dv_N=+Fr*p_>P9kmllhi;dC=!N4AeEne6w6 z71M}aZo~$y)@d0XY}W>YA@gS#P?5g@dGjN^AoP*I3u8Rw59?FBQfP-6yL~K3_ZFSTq)ax;JF2 zcLzFQe6aG+YCSfYKf3a{Tmk4pK)}F!fDdl-#aSG-G!%8d4Rna5 zl7+)pN#$3=^%A=q!jTobhRY7Xe`!5BuBPHHW-#&S!LI91@t{}i__wvw3Cw*TVvjF0n%QK}y%SMe(G+>V() zcgfz`S+=#;9k{mMw($5y=i2H2`JX)BJ6FU$^h~#ZgJy6X4U8Xa{9VE} zoRb9M;O{*QqJOqH{Wf~=$U%)#yPEM2ov%K{kmd}kWN8kzY%0|EXtC3gHzT*?EH%KrF9 z^3YP50vZ%;xYJ5S&PzT%uJ3o@jT_RO+ceDC!W80)nJ*L!6S%_4XMV|KICY*6N}#=| z6jCv}_7nCDpzJWg-09Acdga9L6y$b_4m$qThb+y%az?IAbf2zz!^ z#_qp3d)pi|&=IB^t&JBq7$o2BziKsw|DGd*vbJ4;SFTc{e{R$)@17$fj8k~%gr+yx z<>I3TUP7Y*Puyr9`Zkx)?mvu1n@EA!-A$rK2+nObFE(PQr?GlBZ=Q_?N%-ZOb+!}E zxtuX$MyHb-wcuFm!9UnFbEnDVY0FiPZ@xHaZ!&l!KDI$uSt_ZaN2W^j zt{&?=hrQe=i>bfB`#m{xe6qV?rK2%cN2VvY8O9)0O4ldtl%SHoC!Qkw;@SBs?;iJfgB^BFAcK&Lme%kk~+I9q8-3Rz>bsi_(!OQq=FW@cs+oia_`16^!~Tb3w6{CG)A; z!FC1^Irw{L1;pYsDPG3!^kw@r8xUj~fAI>3%zLYY18~}^;=$WB>di9Dho~_NSSPf1 zyHoVF7uO14nUFyd1e_DE&3bPbFN+3vyQUh#qb4ezsdtT%Vcmas^F|UvwFKOENL1*n zD&}X2aw)mm(!_iZy<~QFl{@ZrjU;obTBn1NVH0k%gF>6sxR8m-=-9f>*df`b+t_t_ zmQ1>k-mXxUodAf!@NLy|Erp_$o~f&5UWKZ72D6N{SQoj;UGozbQ^*3LIXVnnrGHpx z?e$LYL(40^YPkp-$q4(`O! zSa9v0(;e4Ew;~&lrKegMK=#TY*~i?-sf{XBKURO;>bGD$$rUQDh+A7%_CldxooY49YBpR(w7*E2=}mla zNQx-LPY1;rT!-oxDU(zd7{=rxr%Bx>d9{17ak_h&>vXIyKFH-eDluZ?qI6>?pokIn z8$TC|wF59?l<0|}x`om={jxt%GeEz#3JrsiKaIH>y=~<73{HXFKf^#Vc~PguyW}f* z){y}zY8Twb#AUHPexmH0A8=hNbE5OUvelstI0{G`6*yid@jTXyi*!QcC6 zK=94-t#ZEo`!$IP@OO#g%mrr>vV*^Os>j;qwv2xl=j9R7mhk(=yc7HEDjG>!>ZJ&N zVxiZM`f%#=t$aVe<$@!wbGK!8!PQr(&~r;W1#gw)|*e z2ACJ@2E;cZ8sVek&#zVjq(v-voI_zGt(aeW#Z=fNH^P2aaSBF%Sn8m&d$Vgyrq^$| z=vtG-dCa4**|AX_fLjB_?@~&WtB+@3F{mb-m_9ea*Sr3{h{&)9LoIoc*<^ILrTbL} z(FkEX&1loV{N}G$z1xG)@yd7}e^HOI`^GI3XBMY}zjtmxJQc26d-Ql_XRgKp8S>`( z3cC?X@ACx|Cw~eXi=yyT{-ssE57@mGM)tR2XyHl-j#clf9E{@4-GmUEvii2d7o9Gv zpX*NJlQt~Q+;yzK|1aGWWkqb?MHCK-`P{K!*z4ttw!cn=1%IzfUHwY!kSv&wk-@X* z;ID(fcWyvD(Nf?i=In6J2l%52u!-OiO3}Z-@`qKILLrIob7&TSt`*|VKb6-j3jV^u zYfOt#5$gsf6Hx+~?e}5ZXzM^*e=zcXw{S4(@%hm`{%e+7@b{{}f+g)+T3lG*2giWn z;O|{67)wHguiwH) zZv>om#rpdUdOg~Oc9YiED-i7od#r&#pYQu=opT2QSG_)~Ylk0>g(nXFI{16XTGDCK zvsU&;aA3gZV_D$L2pYg&C;@)AZ2q+#@nKRUMkf5{E8g?Fxeo@;>%S&7Gzvk(3g)&G zSamld3~IO@325mU{Nibi#Qx9?CbyM9WR`2=%YMei25`_jp0BU<&EZq^1LNSYgTHs* zfvY{xs^3NXB)pYR9xPf>BS<0fo2bwFXXb-TrgM0MgqAemBb@$_P5-|s;+&59mDM}o zCz4`N`#U>ns=PpFuU=26o^8jjguNa;Ns3!#*A`NA)Qx;de&s)`L*3pi^o&f~8MmCZ8ncX?Tw#JnZ@JS7mfR1QxDhXPf?_?W%|IHCcL zdp22^T7EmT9j4peF`WiZF$pP>^7!4+^^f@S-e@3lwf8qXhlK7R`?&hk69-~=1(}R& zpa-Q?3;2Uxf)9E$2pY(n!)fY*znJ2;7nncI^c@w^io_}he;xe2k9zRLvLY|qpe$nG z8b)(IP}uC}1{`Sc-(U#{2_3}FJZe^QssJa*g`j)skIz-)Ek36}-XTy3*k!#+1}1!H zd4hh45xc(gE0va`$@w|SSJ=E=*?-Aj5ccW@#FdVtujHphHclQtcJSB1-#gcmP~O>h zl8!j#0r5AiHsJ8#KU4Y1Ij2aXTl=;wN*lts=Xo>)n%Mz~)C+hCyl9>VqPnbSeH0*v z!XE&>A@#-4*N*xbj**r|!N*#B(;?Hx06LG`?~AbB`+QOFM&9*Npg!*&?|UnJ4cYjO z;IIC9S#t2#!QcC+dHfY*UH}Fw{QU~}`-Sen5k+nBs+6q|4%`AI(63Na#xx=Iq&4>W zqJe;FY)I#VdpOn<^e_Qw>h@ipk^UI`4Mjuqfi{tFSjp;q6Mm^T6r%xuI1RC_8nxSVzo1}V;sutEX1H+?h5wxke3vVC7N=*}t7=1WQ9MT5qlmnRPXI{5p^ z@K@Ty3V)w{9W=kp9k_RP*TCuk#p-t66S2tMI=h=h#Rz($(X@4IPD8W%Dnuvb*!ovO zyB!F#5)FCmE;9q>iO3(7@)hCr1GC6D%R$$p9{K22U(tgTQR@YS19;u&ySn}A7mj<< z{!Lr{v#>XE{nw770&YJ)Tupn^Q{c<*+P$K`aXjw}*joF*x>{}NC;l$g9?E{n^0TK7 z{yO-3hg!NBe@*%VXJ2aMFilMh0!@@ ztRAVf4zVkDtmb}%tuMmzT(f7j;zq2{hZy(P1LL68t&DhPu+L3#hl0|Gt$5&9_xVEe zz2(Te7>o<3`vpjKJ)U=5E4Yq7$dbPixA)6?OMFO$uDsRz8u1HLdmFC|>_y8DG|#_FiXDR}3H3F1OtVb?l`C?Www^8gzLkh;aZ=6QF5PuQ>A zZZj6*kjJYw9D^b6yRT*a3)@G#b$PC&^50MrB(~6nhY$hFkQk>N{Jm98&)wuZ>&hjM zpFIInC9K+f@?`PZ-)X@4(#kst{6-w2TPdpMHnz!UJ!vpOe^9k3l=4-Y#@1SYc;$-Q z_7E}@BbE(!{4quN{q#kMw#hl$7ECEZ>93B|NXYNlM-Z)<;Iq#i4Ddc6Z3{R8e6a5M z+vK`e)ynuf{C$W&N;1DtTYU7;$$xP0_YSr2U?M}i?oJ9e%ZCqYPnXRvvjGvdkVx{< zLh5)n^Ti#dwJQ=~%aaszZVzb|dgnnnATaH}a_`CQz6pMTi$Om7o-H0}Ekl@mO&!b| z#H+O&6F#f}w%S(U=(KR|Z(}d*9_yBMQ0{be|}l}pGkcM#lvjq*|O7q`2Xx(yN;v4 zwhbp4U8#eKPj=R0WaDPc&>%g&@x?9s6vs;r&`t6 zhtgn~VRs0ssia!lA?H$a-)x?a6`kr#6YvxeHK}VW`x2mTJ;jC0|4_Rd6{2;s7Fwl^ z2=%-yrGBC0KgX=_&j1$#pnv!9{CkW8BD(g;pz;RsHQ0*i$==Pl|9wNyu*t22)Gl74 z%14T(>Dqw^X(KeQw}C#ay1X{B1783)Q&g-j=PhFmm4uY&h--DNiTC^pLU(4gpvN+` z27lL$G)e{N(U6Rz%@YmIw6#O^OeJN#~vJmZQzgYWaTHsiH3vwH6D>cxs)rqZWhvhRZ z^pBAVLkrsOFV~x6=4Eb-Uqew!m6%>O@X$DZJ2*7h)K~{cHw$`74F49?*2V)2Df=pUfj@f93qR-P`S;j0kYgxvSGl=I{ynqeYi01%RdfAp zXdfuYWz}V=KDu*WRLnRUx;b{%;mHS%<)A|don=?7awlq`-ahw_&Tr$@~W z11Jb#5<2H{J|YwwGj{IV%c7ecH!t8PfgdBdnD-OTDH;>c*bj43{8kqWTrM7-e~&_} z2lRA(c{o^SP#GOTfcR7anACtu0`m2Fuuk!TPD3cGfxryo91oWng$`)sAB^9zsAn^0 zBv#N;Tsao(ko(S&<6W$Z&q$|D4k|>hCJq;GFSWVDXfzFWVHDd^cI`4SipF_f*St{i zK3wL`P$YyKGFgs=G>!ueD}R{N0wP(x{OkGmKw$KGx;{DA4^zGooOsc-CzPX|^+`}s z)H4|&Z#Kdd71~8XTDbkcN3DX^++%sokL8V*EmK?gegjhB+gx z4R)upo`(%lj;zmXX06FL_!pra%{Z>rAQ0!G!eny&XCdR4Yge-Q8}-id72hg+eGAOm zANs^Zv<6-X_WXOq8gNna9&Aj`g`v9Pir?ci2ai>G@7b#BqB&i+3(8r~mMJF$U9`wt z_TmP#%3W3A;=9j7+Iwrtz}qDaDooZ9EouQD)z;m-;X6mA&byTl<6|K_Loq5HJa_gD zl57btr%3)4h`?B8gZ&tF8-^<`xoUOiECnYW4tL(uNP4ZD<0)680T&a z2>;%4#2d)J3YoezvWpiYJpUd5eO7Hu&YhDUqNdfOkGmmN4OmklW=~kR7oypeU6K5p z{4K*>l)L+Q9;k!1bRe!3j|cLtU})K0z&)~(%e>ie9k34RcUde;hu*AX0{V&B>|n7c zMg?ce%@*vYqTo%2v5Z4OYbcqk8ggXiC45N+`<^j*Zkc&5EQkUCb+3o2f5UTY>(GVVB= z)vc{gwte$13W_uLB_#B+BYJkBlvF&!S0t8_i)lkVrrNNOfVoJZ2E@_(*Ml+Kf*{RKAmaqQe4bWq2J`?vq z%`*NIse!a(ZwVKz5}p-}Gg_z$+XlvW5Hc}KUaMER*E*@cCQ=4+BkvkmCxg>&y8J|81p=fJY>L*ZpUm0%n74ippG4*Hi37@=sB zpx1jLayTlaOsVfISf#8aEWb|o2Fqp870M@4?MhAgas8CxYAS@zKnAz9ZL4DqRlBy3 zY$7wYMO_zbCdLvpCPc+yRQh7;z5WI{&fwfD8N$Q!?@;PJ6 zZkD2*naIi(RbBv65tSxaS98pSnFS%!{%*o&fkBO96l3yU{;dZdUrFuYogN-3(=v%P z`M=$Se!1Q(aGU-;|<+g5@z*%=L|RglmJc>ZY@O%rUn%g{-*FsH|Hvr-fXan}_ZMVJoqk7rYiA ze=d^TYeSz9&QrUbV_zm+GLsrrIXC(41H;ngs>&>ljhhfz-|1&TXd{WQPiyS*r5!Ug;?{y_=PIW%(DOm^l7 z^NxWkRcby&A=$Y#V9<{+@%X~WBm&%+xGSvKh=GT$}X3{KejxtbYWXzJvc*S z1~`J!uw6x@u4rpEnhLf7-?AWUAKJ{up_1xHT#eqOnBD`_9em6-{jTzFJ!(1~GPeXH z$0qWL|-E2{~n59^JdE7-#@pxhgEpL{4_{S9*E*uz7}*vDfq_D zsh~An#l?ePlcH7YHdsCn=WWCu{UW*TqyBsPU6YbqtOs#9`c5$~YZ`Ub)cuCF(}g12 z)jA)6QoXH5OS|seup>I`-0rSYRNs-Ub3;!4rW0)Rl@!3OB@7eejT6tuyPQeQE%!67 z|BPDP>FTBc$7zuD7her~{(T({RpYvxq?q3j02_{Ral%j*~ zHUXQ}_W7v)cEoIV3VI{DfSIJr_w*M=pX)9kMd8976Kk^q)PPde-O4X0H_~_FOLl>4 zA=HGMgy*>#BFTa@9^iS{^Y3B&3kZ!F?WgfC1Ml(;jB;k(VsPVXyo0pNmG9Jq`|dHZ zy9h77`R)J;!tM}}@nefkV^=pBAZl@Q@lUC}Ye;Z9zPMQH&y%~OUm*q*+@#?>#lIyU z#1tO{z2ub{f=F&BU0s;W2SCzW4=^IJ6WJQQ&xY{)dldfyLVa#!Um=#87!%pft@T~W zmbBTBN@c@bs_H~R4ELb}cIhy)t!&*21r#;A%e}y{q~^nsO4^wHI-xiBayZYM%}G2_ zNYeuXjd9!_`mmX=SbMqKyH-88E?wR@E!t`?qRTn4{nn)vg7W2mQai5TWaZ!X2?Cac zG3|_N3tpl^Rg7+ouEl9r^@bJxjnS3qAWBmVYBlIj?=KF|zen*eAW&yr_UGgCfFS_e zmUw3^_^tX*z%%=(sndJ`<(cS|DyWLgjvB|s2Ss1<6pf+q&Lx_CMUn%X-axzBWsFg9 z5Abivb0OfZa3nK*+KgVpH2kurV~YY?XykIh`02H+5}$pB!y<~l_jkeYEir0M~j4bC~DMapG1p|2aaSas;U)KPIAa3 zkgqNID6j7jI5m$f@`kOH``E;{UVgzxq@AKY=(t|<9D7_=kC4=x0E zo^Xl(572Ia{i0I@X*Bxh!;9Ve@=Mcu{ymI;5nuuSL=fR#suBXvDf`$E9cfJot_R1| zq*2k_V&A%1vup9Zy?zDM!{Pj8rsizQZt1bgO~y?{W>&eTy-A-yPRF1d)d4z7yywdW zI`W2!?pew&_~^%O2>J<8NFrP`U3J&wUnzvCagH&$DKXB=hov=ig7` z-_!4p!?B-iAZk*GoDHnxr0Zbqly@_y!9L2>y#UJVS3uJqK;bLx%2dk@7Fg{)7#}CD zpNGmdTc8)>*`R$qP?paKoi#X->VV;0Rs(K1qU{fXP25S6mFpvM8m*FNZ@;q$_H?JNu~SLFZmbZkF`!9dV)VvWC1kOtb07F^<) zQSAkNX`X)%z{#3vLge2)?j6r+&@CqCUlxtm{A28k6;T}QzA8FRE{rtI01Ck z13mO-=MYxRS|CeDgmHrGyMz87`V3Mt2%KM}%Jp~<=QP3x=n;ER+=$)NUNLgG_A1=0 zoSX5>2oIir4@6+jT};@y?3iw6;|}v06+< z##8|49eTcmW-1N1+t;B#4#6NaeL=7AKZhxFdmv&o`ChU#nfM$Bo7#&uU3mVzE%1hE z24gikX45oIQ0{#SK{7Ei_(JKYATmJ*S*Sd-9;1Wzgo=WXTlf5X8>bjdvAxrt9$&D2 z1qOZEKM(->dh5ZDLT^ONI839^x?T4W?3@8V=#D5e6K?Mwo`3HG&V^yk8=l|^=dwtj zwkz}lwf~?i>}%n2&a!@~#-`_E3*9t!@3BK%n>Dq=bpYkC8O_7lNp%LB)tYtt-1kB9 zgJuKD&V#X|8*v+>O>?XvYR)ctr%K zlNtSCTK2~b&wcuSdOb6l=ig_Lq+S#F2|(k%W#VHQEx@VQ=$yt+%qXO3;f`NAvlMZz96zutTpM4`Ad+;-`yxR>AEhrD75>z0v`5t3bPIT>f?lZ`7{9d|M zZ{pID^X1~{*Yocl!U#^3Z*_WmEU`{#;lX=9I4>k!I~_sTNKa#NfaUY!lLwb9!r#Lr zj{cbm8jeC8j@N%Z|L!3f%8b()PSx*KV*C(9pP)M;(&zRN#!0fJ03Vo_cR4+Aw%(qn zxP+$|aGEL|z52VH|J5i6E+6lF@cerpLN$#YdlC4bBha#FkVT)N0te4fhoRWZrl}Ra z@qgL7vgFor7rKSeo~4J^W}8fBwx89-!&nm;@|^=9;rwkVFeWZT@u05R!})2Vr_E1fwEx1;Q6Ia% zp|!5d!RC+cC$9Ya0Q_rvMmtIJx1N#@$4ta-@Mxj@5IqDQ!e6dpR-aeg#L|ojmQNXFL-obbmA- zq4clFDgPQ!a}7V_$urok(iNJhO-1G3J8-{H`wcx$P$U0R{Lt?U1w&+lb^CQ9a(N^@ zHTH;q<&-}33nJJvB%mq}wgfrf5Gj@?stOHtFX;XcQLq49C;&$Oni8Xf5SJD02sma; z$4S&d_fq zSZvj)!IJax8-n*sgsOjxOz@&$X3e?h*}&dV@~z(;}gRvJ{cnYnJN zAeqqLcF|@(KW%~>B9eorg|pbY(a55>W{;m5rkuV3Ve6m{1%Gb>{#dK>1&7{n&3VhfIscBg5uj;6RfSLI{a>X< zCPDx~q9j+Wgx~HY3y?FZ*|eh+?l<*(5Xxjg%>D}fCh&2& zh<(=yvZy?2*IQqi+-4`|$*+yZWNpy+TruiE+85|}G#ZhcS=jHOARjkXzVh!yVBGoN z8KzzQ*2Z5tS&on!JIAtaWOJ8A{!G#&mI?$KkyD)M6CgRL7-S)N)e0~KgY8F3>QII}r3SvC2{8H#nQdg_+l42x@6;t8 zHnn$Je}f?P+Y&UNyF3&Gq{gvV{!NgvHszysc_z9iT*cN~C!)R?jQIR#!)$nRGtc;k z^vf9XkI%6+HC#UPcsC|&i=gr#+ZPh;+%D!=(h7pp8PJ|+~wS~o{ zcEyBo-g-HDQvQa%VGohGv=;G@1IZ0fDhRi?Fd8@35rGlsGe!~B^w~YJ&-<&vWL)00 z=22Gu-2+nxq;E1h;IDH(`ay*xNNOQTkKD+icqLX`csYQgS8O;}Xk>b|IR%u~0lGDh z0sXoxht-528-2AQi#ww@3|(c^6CswtR_-`QdtJj}qZI_;hU`JoCYy0%U3H4Fm@%h= zTLhr=Sjz{lx>M|n#*z{<0fS4jmTxL5|LzVT3g4BfxYefpZQbusI#%COCFvIcdH>_P zDR2$#~#tM>m9-*zZXndrFE-KxX$Iet9|95~yqs`Ma?v_&&9GnwyyH`g>bYUpyfBnGC4BtfGgA$C zHX6mszLkI9fe(#;a!8W{ZFzLXZtVXOyKl=2`vx*?UklG?8nj_UvTqbN*WY)1*)Z2A z+>Al-*#3WEDz2%h{QGv$uQNbg0h7#tAluGU9{y>W{m8+jJ-7#NxyhS<2meOeMDvJr zHL-|~i=KvYec4+h?1h>tjR8702-x&B3>%hmhyc+vKguBIUaY3y%D-;|x4+H+aSpMp z{2Lv6Q3|tpDba7^-J^{}hQJvuzo^0l-kbqSSJBGw#kQvmZDWF9>JfgvGVd(B^Ft2V zBeIxMfs@9ABA~?Z5|M@>@vqWUeZY!rF;vf4<=;0V{v`v1^So(w;5oW7T5B0c=WSOL zWdc8YjtMCh65|v-2`{ldtijMUb4HS6N(g&FUadMVtKTD{|KX*97VqVJR(Kb{FHp^? zyKKJ-+T4uHm1`^i{$t?ZF+i{kb*JQ&sI>|HAp2W8qbU``Vv{?650n*K#F-i^FL6f% zMCoyK!ewdLVd$j$sK#3^;{hmnS= zIh<=d*XaCm^d0x;PVEmk{TI(@t!g7^#wpzzrw^wZvBpUsc(n-Br=FKUic3u7(J*zqdn zYIK17uCh{4ct27HRIoJHvfmM$v`C5<$NJe@1bu{9EyM zjLM=HK^oQGfIBhbiBGUF_3_5O7$?u{7Jl^aORH{Mjs;Nl!iQ}V(F;)udbCosA|u%G zMx1-XkC>5I;87hn&c)$4s}@Hkxf@=WxMOzH74J^N@V1+j*t;Bv+&wJ}&V`pF<1;Uo zOsm%3%D)vq2It+%_!YSnprh{M@3i5W#q5ZHc?vKTx6T6ggkbsQNyMwhRJLBs@c|;_ z;Q|`lu#j9sa7$T1vN~INzOb&|B|z9MVRu5obh9_0G*KCe=SWY;cMM*rxevS+d?p8C zh%Bn;>T#(2Tk#lfob;m|Ktw%mSWyn^Ra@oNhZ6m|ixyv#omaFuC=M~{4U!JOBKX-P zD?O%LgziQ0wmeFb0qC}~sDdQxoS)Z`VTh!xZdO`XWO)Ta;`Ee4vxoVDaGI0wl>B_S zbWUl!zp7fL+{(WdKb3S`W=ZLLtJL>`RsXDmE9gQszE7R{x(edZkD*t{CGz*fY(kyT% zvhSM(KA%U4P2%64F=2|6(76VW$c)l~vH`w=UTrNuWO`-YCRh9&RQ~-O=uDzxLu<(= zfd}rgVC@O;IQ0eQTn9;<8%8PF#@Fh!u!@gC<=@YNF75QKVd)#CW9TO^S|0zjIpoSU zwYFGQdpIlK<`L|;0e~7XOGze}L zFXs925cuG7zX2S5pB|C>U!31mQBnE#Tr^*Bh=kiWR3 z(l564*qT;)+BSvdMbq_iuH{SO7a)J}x3yaG&Bhw^L(BG})TX(M>|_AQUyP{AH5bKZ xW5;}BX3Q)A help - -INSTALLING COMPASS - - You can install compass using the install_compass script packaged with MongoDB: - - $ ./install_compass - - This will download the appropriate MongoDB Compass package for your platform - and install it. - -DRIVERS - - Client drivers for most programming languages are available at - https://docs.mongodb.com/manual/applications/drivers/. Use the shell - ("mongo") for administrative tasks. - -BUG REPORTS - - See https://github.com/mongodb/mongo/wiki/Submit-Bug-Reports. - -PACKAGING - - Packages are created dynamically by the package.py script located in the - buildscripts directory. This will generate RPM and Debian packages. - -DOCUMENTATION - - https://docs.mongodb.com/manual/ - -CLOUD HOSTED MONGODB - - https://www.mongodb.com/cloud/atlas - -FORUMS - - https://community.mongodb.com - - A forum for technical questions about using MongoDB. - - https://community.mongodb.com/c/server-dev - - A forum for technical questions about building and developing MongoDB. - -LEARN MONGODB - - https://university.mongodb.com/ - -LICENSE - - MongoDB is free and open-source. Versions released prior to October 16, - 2018 are published under the AGPL. All versions released after October - 16, 2018, including patch fixes for prior versions, are published under - the Server Side Public License (SSPL) v1. See individual files for - details. - diff --git a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES b/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES deleted file mode 100644 index 8c9e17e3..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,1568 +0,0 @@ -MongoDB uses third-party libraries or other resources that may -be distributed under licenses different than the MongoDB software. - -In the event that we accidentally failed to list a required notice, -please bring it to our attention through any of the ways detailed here : - - mongodb-dev@googlegroups.com - -The attached notices are provided for information only. - -For any licenses that require disclosure of source, sources are available at -https://github.com/mongodb/mongo. - - -1) License Notice for Boost ---------------------------- - -http://www.boost.org/LICENSE_1_0.txt - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - -3) License Notice for PCRE --------------------------- - -http://www.pcre.org/licence.txt - -PCRE LICENCE ------------- - -PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - -Release 7 of PCRE is distributed under the terms of the "BSD" licence, as -specified below. The documentation for PCRE, supplied in the "doc" -directory, is distributed under the same terms as the software itself. - -The basic library functions are written in C and are freestanding. Also -included in the distribution is a set of C++ wrapper functions. - - -THE BASIC LIBRARY FUNCTIONS ---------------------------- - -Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk - -University of Cambridge Computing Service, -Cambridge, England. - -Copyright (c) 1997-2008 University of Cambridge -All rights reserved. - - -THE C++ WRAPPER FUNCTIONS -------------------------- - -Contributed by: Google Inc. - -Copyright (c) 2007-2008, Google Inc. -All rights reserved. - - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -4) License notice for Aladdin MD5 ---------------------------------- - -Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -5) License notice for Snappy - http://code.google.com/p/snappy/ ---------------------------------- - Copyright 2005 and onwards Google Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - A light-weight compression algorithm. It is designed for speed of - compression and decompression, rather than for the utmost in space - savings. - - For getting better compression ratios when you are compressing data - with long repeated sequences or compressing data that is similar to - other data, while still compressing fast, you might look at first - using BMDiff and then compressing the output of BMDiff with - Snappy. - -6) License notice for Google Perftools (TCMalloc utility) ---------------------------------- -New BSD License - -Copyright (c) 1998-2006, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -7) License notice for Linenoise -------------------------------- - - Copyright (c) 2010, Salvatore Sanfilippo - Copyright (c) 2010, Pieter Noordhuis - - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -8) License notice for S2 Geometry Library ------------------------------------------ - Copyright 2005 Google Inc. All Rights Reserved. - - 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. - -9) License notice for MurmurHash --------------------------------- - - Copyright (c) 2010-2012 Austin Appleby - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -10) License notice for Snowball - Copyright (c) 2001, Dr Martin Porter - All rights reserved. - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -11) License notice for yaml-cpp -------------------------------- - -Copyright (c) 2008 Jesse Beder. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -12) License notice for zlib ---------------------------- - -http://www.zlib.net/zlib_license.html - -zlib.h -- interface of the 'zlib' general purpose compression library -version 1.2.8, April 28th, 2013 - -Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -13) License notice for 3rd party software included in the WiredTiger library ----------------------------------------------------------------------------- - -http://source.wiredtiger.com/license.html - -WiredTiger Distribution Files | Copyright Holder | License ------------------------------ | ----------------------------------- | ---------------------- -src/include/bitstring.i | University of California, Berkeley | BSD-3-Clause License -src/include/queue.h | University of California, Berkeley | BSD-3-Clause License -src/os_posix/os_getopt.c | University of California, Berkeley | BSD-3-Clause License -src/support/hash_city.c | Google, Inc. | The MIT License -src/support/hash_fnv.c | Authors | Public Domain - - -Other optional 3rd party software included in the WiredTiger distribution is removed by MongoDB. - - -BSD-3-CLAUSE LICENSE --------------------- - -http://www.opensource.org/licenses/BSD-3-Clause - -Copyright (c) 1987, 1989, 1991, 1993, 1994 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - - -THE MIT LICENSE ---------------- - -http://www.opensource.org/licenses/MIT - -Copyright (c) 2011 Google, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -14) License Notice for SpiderMonkey ------------------------------------ - -|------------------------------------------------|------------------|---------------| -| SpiderMonkey Distribution Files | Copyright Holder | License | -|------------------------------------------------|------------------|---------------| -| js/src/jit/shared/AssemblerBuffer-x86-shared.h | Apple, Inc | BSD-2-Clause | -| js/src/jit/shared/BaseAssembler-x86-shared.h | | | -|------------------------------------------------|------------------|---------------| -| js/src/builtin/ | Google, Inc | BSD-3-Clause | -| js/src/irregexp/ | | | -| js/src/jit/arm/ | | | -| js/src/jit/mips/ | | | -| mfbt/double-conversion/ | | | -|------------------------------------------------|------------------|---------------| -| intl/icu/source/common/unicode/ | IBM, Inc | ICU | -|------------------------------------------------|------------------|---------------| -| js/src/asmjs/ | Mozilla, Inc | Apache2 | -|------------------------------------------------|------------------|---------------| -| js/public/ | Mozilla, Inc | MPL2 | -| js/src/ | | | -| mfbt | | | -|------------------------------------------------|------------------|---------------| -| js/src/vm/Unicode.cpp | None | Public Domain | -|------------------------------------------------|------------------|---------------| -| mfbt/lz4.c | Yann Collet | BSD-2-Clause | -| mfbt/lz4.h | | | -|------------------------------------------------|------------------|---------------| - -Other optional 3rd party software included in the SpiderMonkey distribution is removed by MongoDB. - - -Apple, Inc: BSD-2-Clause ------------------------- - -Copyright (C) 2008 Apple Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Google, Inc: BSD-3-Clause -------------------------- - -Copyright 2012 the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -ICU License - ICU 1.8.1 and later ---------------------------------- - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2012 International Business Machines Corporation and -others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, provided that the above copyright notice(s) and this -permission notice appear in all copies of the Software and that both the -above copyright notice(s) and this permission notice appear in supporting -documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE -BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization of the -copyright holder. - -All trademarks and registered trademarks mentioned herein are the property -of their respective owners. - - -Mozilla, Inc: Apache 2 ----------------------- - -Copyright 2014 Mozilla Foundation - -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. - - -Mozilla, Inc: MPL 2 -------------------- - -Copyright 2014 Mozilla Foundation - -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -Public Domain -------------- - -Any copyright is dedicated to the Public Domain. -http://creativecommons.org/licenses/publicdomain/ - - -LZ4: BSD-2-Clause ------------------ - -Copyright (C) 2011-2014, Yann Collet. -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 source repository : http://code.google.com/p/lz4/ -- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c - -15) License Notice for Intel DFP Math Library ---------------------------------------------- - -Copyright (c) 2011, Intel Corp. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - his list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -16) License Notice for Unicode Data ------------------------------------ - -Copyright © 1991-2015 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -17 ) License Notice for Valgrind.h ----------------------------------- - ----------------------------------------------------------------- - -Notice that the following BSD-style license applies to this one -file (valgrind.h) only. The rest of Valgrind is licensed under the -terms of the GNU General Public License, version 2, unless -otherwise indicated. See the COPYING file in the source -distribution for details. - ----------------------------------------------------------------- - -This file is part of Valgrind, a dynamic binary instrumentation -framework. - -Copyright (C) 2000-2015 Julian Seward. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - -4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------- - -Notice that the above BSD-style license applies to this one file -(valgrind.h) only. The entire rest of Valgrind is licensed under -the terms of the GNU General Public License, version 2. See the -COPYING file in the source distribution for details. - ----------------------------------------------------------------- - -18) License notice for ICU4C ----------------------------- - -ICU License - ICU 1.8.1 and later - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2016 International Business Machines Corporation and others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY -SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER -RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - - -All trademarks and registered trademarks mentioned herein are the -property of their respective owners. - ---------------------- - -Third-Party Software Licenses - -This section contains third-party software notices and/or additional -terms for licensed third-party software components included within ICU -libraries. - -1. Unicode Data Files and Software - -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2016 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) - - # The Google Chrome software developed by Google is licensed under - # the BSD license. Other software included in this distribution is - # provided under other licenses, as set forth below. - # - # The BSD License - # http://opensource.org/licenses/bsd-license.php - # Copyright (C) 2006-2008, Google Inc. - # - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided with - # the distribution. - # Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - # - # The word list in cjdict.txt are generated by combining three word lists - # listed below with further processing for compound word breaking. The - # frequency is generated with an iterative training against Google web - # corpora. - # - # * Libtabe (Chinese) - # - https://sourceforge.net/project/?group_id=1519 - # - Its license terms and conditions are shown below. - # - # * IPADIC (Japanese) - # - http://chasen.aist-nara.ac.jp/chasen/distribution.html - # - Its license terms and conditions are shown below. - # - # ---------COPYING.libtabe ---- BEGIN-------------------- - # - # /* - # * Copyrighy (c) 1999 TaBE Project. - # * Copyright (c) 1999 Pai-Hsiang Hsiao. - # * All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the TaBE Project nor the names of its - # * contributors may be used to endorse or promote products derived - # * from this software without specific prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # /* - # * Copyright (c) 1999 Computer Systems and Communication Lab, - # * Institute of Information Science, Academia - # * Sinica. All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the Computer Systems and Communication Lab - # * nor the names of its contributors may be used to endorse or - # * promote products derived from this software without specific - # * prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, - # University of Illinois - # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 - # - # ---------------COPYING.libtabe-----END-------------------------------- - # - # - # ---------------COPYING.ipadic-----BEGIN------------------------------- - # - # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science - # and Technology. All Rights Reserved. - # - # Use, reproduction, and distribution of this software is permitted. - # Any copy of this software, whether in its original form or modified, - # must include both the above copyright notice and the following - # paragraphs. - # - # Nara Institute of Science and Technology (NAIST), - # the copyright holders, disclaims all warranties with regard to this - # software, including all implied warranties of merchantability and - # fitness, in no event shall NAIST be liable for - # any special, indirect or consequential damages or any damages - # whatsoever resulting from loss of use, data or profits, whether in an - # action of contract, negligence or other tortuous action, arising out - # of or in connection with the use or performance of this software. - # - # A large portion of the dictionary entries - # originate from ICOT Free Software. The following conditions for ICOT - # Free Software applies to the current dictionary as well. - # - # Each User may also freely distribute the Program, whether in its - # original form or modified, to any third party or parties, PROVIDED - # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear - # on, or be attached to, the Program, which is distributed substantially - # in the same form as set out herein and that such intended - # distribution, if actually made, will neither violate or otherwise - # contravene any of the laws and regulations of the countries having - # jurisdiction over the User or the intended distribution itself. - # - # NO WARRANTY - # - # The program was produced on an experimental basis in the course of the - # research and development conducted during the project and is provided - # to users as so produced on an experimental basis. Accordingly, the - # program is provided without any warranty whatsoever, whether express, - # implied, statutory or otherwise. The term "warranty" used herein - # includes, but is not limited to, any warranty of the quality, - # performance, merchantability and fitness for a particular purpose of - # the program and the nonexistence of any infringement or violation of - # any right of any third party. - # - # Each user of the program will agree and understand, and be deemed to - # have agreed and understood, that there is no warranty whatsoever for - # the program and, accordingly, the entire risk arising from or - # otherwise connected with the program is assumed by the user. - # - # Therefore, neither ICOT, the copyright holder, or any other - # organization that participated in or was otherwise related to the - # development of the program and their respective officials, directors, - # officers and other employees shall be held liable for any and all - # damages, including, without limitation, general, special, incidental - # and consequential damages, arising out of or otherwise in connection - # with the use or inability to use the program or any product, material - # or result produced or otherwise obtained by using the program, - # regardless of whether they have been advised of, or otherwise had - # knowledge of, the possibility of such damages at any time during the - # project or thereafter. Each user will be deemed to have agreed to the - # foregoing by his or her commencement of use of the program. The term - # "use" as used herein includes, but is not limited to, the use, - # modification, copying and distribution of the program and the - # production of secondary products from the program. - # - # In the case where the program, whether in its original form or - # modified, was distributed or delivered to or received by a user from - # any person, organization or entity other than ICOT, unless it makes or - # grants independently of ICOT any specific warranty to the user in - # writing, such person, organization or entity, will also be exempted - # from and not be held liable to the user for any such damages as noted - # above as far as the program is concerned. - # - # ---------------COPYING.ipadic-----END---------------------------------- - -3. Lao Word Break Dictionary Data (laodict.txt) - - # Copyright (c) 2013 International Business Machines Corporation - # and others. All Rights Reserved. - # - # Project: http://code.google.com/p/lao-dictionary/ - # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt - # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt - # (copied below) - # - # This file is derived from the above dictionary, with slight - # modifications. - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, - # are permitted provided that the following conditions are met: - # - # - # Redistributions of source code must retain the above copyright notice, this - # list of conditions and the following disclaimer. Redistributions in - # binary form must reproduce the above copyright notice, this list of - # conditions and the following disclaimer in the documentation and/or - # other materials provided with the distribution. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # OF THE POSSIBILITY OF SUCH DAMAGE. - # -------------------------------------------------------------------------- - -4. Burmese Word Break Dictionary Data (burmesedict.txt) - - # Copyright (c) 2014 International Business Machines Corporation - # and others. All Rights Reserved. - # - # This list is part of a project hosted at: - # github.com/kanyawtech/myanmar-karen-word-lists - # - # -------------------------------------------------------------------------- - # Copyright (c) 2013, LeRoy Benjamin Sharon - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: Redistributions of source code must retain the above - # copyright notice, this list of conditions and the following - # disclaimer. Redistributions in binary form must reproduce the - # above copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided - # with the distribution. - # - # Neither the name Myanmar Karen Word Lists, nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - # -------------------------------------------------------------------------- - -5. Time Zone Database - - ICU uses the public domain data and code derived from Time Zone -Database for its time zone support. The ownership of the TZ database -is explained in BCP 175: Procedure for Maintaining the Time Zone -Database section 7. - - # 7. Database Ownership - # - # The TZ database itself is not an IETF Contribution or an IETF - # document. Rather it is a pre-existing and regularly updated work - # that is in the public domain, and is intended to remain in the - # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do - # not apply to the TZ Database or contributions that individuals make - # to it. Should any claims be made and substantiated against the TZ - # Database, the organization that is providing the IANA - # Considerations defined in this RFC, under the memorandum of - # understanding with the IETF, currently ICANN, may act in accordance - # with all competent court orders. No ownership claims will be made - # by ICANN or the IETF Trust on the database or the code. Any person - # making a contribution to the database or code waives all rights to - # future claims in that contribution or in the TZ Database. - -19) License notice for timelib ------------------------------- - -The MIT License (MIT) - -Copyright (c) 2015-2017 Derick Rethans -Copyright (c) 2017 MongoDB, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -20) License notice for windows dirent implementation ----------------------------------------------------- - - * Dirent interface for Microsoft Visual Studio - * Version 1.21 - * - * Copyright (C) 2006-2012 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - - - 21) License notice for abseil-cpp ----------------------------- - - Copyright (c) Google Inc. - - 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. - - 22) License notice for Zstandard ----------------------------- - - BSD License - - For Zstandard software - - Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 23) License notice for ASIO ----------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 24) License notice for MPark.Variant -------------------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 25) License notice for fmt ---------------------------- - -Copyright (c) 2012 - present, Victor Zverovich -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 26) License notice for SafeInt ---------------------------- - -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. - -MIT License - -Copyright (c) 2018 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - 27) License Notice for Raft TLA+ Specification ------------------------------------------------ - -https://github.com/ongardie/dissertation/blob/master/LICENSE - -Copyright 2014 Diego Ongaro. - -Some of our TLA+ specifications are based on the Raft TLA+ specification by Diego Ongaro. - -End diff --git a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md b/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md deleted file mode 100644 index 550ae4ed..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2014 MongoDB, Inc. - -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/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md b/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md deleted file mode 100644 index e60e0cd0..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md +++ /dev/null @@ -1,72 +0,0 @@ -MongoDB Tools -=================================== - - - **bsondump** - _display BSON files in a human-readable format_ - - **mongoimport** - _Convert data from JSON, TSV or CSV and insert them into a collection_ - - **mongoexport** - _Write an existing collection to CSV or JSON format_ - - **mongodump/mongorestore** - _Dump MongoDB backups to disk in .BSON format, or restore them to a live database_ - - **mongostat** - _Monitor live MongoDB servers, replica sets, or sharded clusters_ - - **mongofiles** - _Read, write, delete, or update files in [GridFS](http://docs.mongodb.org/manual/core/gridfs/)_ - - **mongotop** - _Monitor read/write activity on a mongo server_ - - -Report any bugs, improvements, or new feature requests at https://jira.mongodb.org/browse/TOOLS - -Building Tools ---------------- - -We currently build the tools with Go version 1.15. Other Go versions may work but they are untested. - -Using `go get` to directly build the tools will not work. To build them, it's recommended to first clone this repository: - -``` -git clone https://github.com/mongodb/mongo-tools -cd mongo-tools -``` - -Then run `./make build` to build all the tools, placing them in the `bin` directory inside the repository. - -You can also build a subset of the tools using the `-tools` option. For example, `./make build -tools=mongodump,mongorestore` builds only `mongodump` and `mongorestore`. - -To use the build/test scripts in this repository, you **_must_** set GOROOT to your Go root directory. This may depend on how you installed Go. - -``` -export GOROOT=/usr/local/go -``` - -Updating Dependencies ---------------- -Starting with version 100.3.1, the tools use `go mod` to manage dependencies. All dependencies are listed in the `go.mod` file and are directly vendored in the `vendor` directory. - -In order to make changes to dependencies, you first need to change the `go.mod` file. You can manually edit that file to add/update/remove entries, or you can run the following in the repository directory: - -``` -go mod edit -require=@ # for adding or updating a dependency -go mod edit -droprequire= # for removing a dependency -``` - -Then run `go mod vendor -v` to reconstruct the `vendor` directory to match the changed `go.mod` file. - -Optionally, run `go mod tidy -v` to ensure that the `go.mod` file matches the `mongo-tools` source code. - -Contributing ---------------- -See our [Contributor's Guide](CONTRIBUTING.md). - -Documentation ---------------- -See the MongoDB packages [documentation](https://docs.mongodb.org/database-tools/). - -For documentation on older versions of the MongoDB, reference that version of the [MongoDB Server Manual](docs.mongodb.com/manual): - -- [MongoDB 4.2 Tools](https://docs.mongodb.org/v4.2/reference/program) -- [MongoDB 4.0 Tools](https://docs.mongodb.org/v4.0/reference/program) -- [MongoDB 3.6 Tools](https://docs.mongodb.org/v3.6/reference/program) - -Adding New Platforms Support ---------------- -See our [Adding New Platform Support Guide](PLATFORMSUPPORT.md). - -Vendoring the Change into Server Repo ---------------- -See our [Vendor the Change into Server Repo](SERVERVENDORING.md). diff --git a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES b/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES deleted file mode 100644 index 3d75e64b..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,3319 +0,0 @@ ---------------------------------------------------------------------- -License notice for hashicorp/go-rootcerts ---------------------------------------------------------------------- - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - ---------------------------------------------------------------------- -License notice for JSON and CSV code from github.com/golang/go ---------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/escaper ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Lucas Morales - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo/bson ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/openssl ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/3rf/mongo-lint ----------------------------------------------------------------------- - -Copyright (c) 2013 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/go-stack/stack ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Chris Hines - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/golang/snappy ----------------------------------------------------------------------- - -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/google/gopacket ----------------------------------------------------------------------- - -Copyright (c) 2012 Google, Inc. All rights reserved. -Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Andreas Krennmair, Google, nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/gopherjs/gopherjs ----------------------------------------------------------------------- - -Copyright (c) 2013 Richard Musiol. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/howeyc/gopass ----------------------------------------------------------------------- - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/jessevdk/go-flags ----------------------------------------------------------------------- - -Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/jtolds/gls ----------------------------------------------------------------------- - -Copyright (c) 2013, Space Monkey, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mattn/go-runewidth ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mongodb/mongo-go-driver ----------------------------------------------------------------------- - - 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. - ----------------------------------------------------------------------- -License notice for github.com/nsf/termbox-go ----------------------------------------------------------------------- - -Copyright (C) 2012 termbox-go authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/patrickmn/go-cache ----------------------------------------------------------------------- - -Copyright (c) 2012-2015 Patrick Mylund Nielsen and the go-cache contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions ----------------------------------------------------------------------- - -Copyright (c) 2015 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/go-render ----------------------------------------------------------------------- - -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglematchers ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglemock ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/ogletest ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/reqtrace ----------------------------------------------------------------------- - - 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. - - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey ----------------------------------------------------------------------- - -Copyright (c) 2014 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey/web/client/resources/fonts/Open_Sans ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/spacemonkeygo/spacelog ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/scram ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/stringprep ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/youmark/pkcs8 ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 youmark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for golang.org/x/crypto ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/sync ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/text ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for gopkg.in/tomb.v2 ----------------------------------------------------------------------- - -tomb - support for clean goroutine termination in Go. - -Copyright (c) 2010-2011 - Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt deleted file mode 100644 index b01add13..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt +++ /dev/null @@ -1,557 +0,0 @@ - Server Side Public License - VERSION 1, OCTOBER 16, 2018 - - Copyright © 2018 MongoDB, Inc. - - Everyone is permitted to copy and distribute verbatim copies of this - license document, but changing it is not allowed. - - TERMS AND CONDITIONS - - 0. Definitions. - - “This License” refers to Server Side Public License. - - “Copyright” also means copyright-like laws that apply to other kinds of - works, such as semiconductor masks. - - “The Program” refers to any copyrightable work licensed under this - License. Each licensee is addressed as “you”. “Licensees” and - “recipients” may be individuals or organizations. - - To “modify” a work means to copy from or adapt all or part of the work in - a fashion requiring copyright permission, other than the making of an - exact copy. The resulting work is called a “modified version” of the - earlier work or a work “based on” the earlier work. - - A “covered work” means either the unmodified Program or a work based on - the Program. - - To “propagate” a work means to do anything with it that, without - permission, would make you directly or secondarily liable for - infringement under applicable copyright law, except executing it on a - computer or modifying a private copy. Propagation includes copying, - distribution (with or without modification), making available to the - public, and in some countries other activities as well. - - To “convey” a work means any kind of propagation that enables other - parties to make or receive copies. Mere interaction with a user through a - computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays “Appropriate Legal Notices” to the - extent that it includes a convenient and prominently visible feature that - (1) displays an appropriate copyright notice, and (2) tells the user that - there is no warranty for the work (except to the extent that warranties - are provided), that licensees may convey the work under this License, and - how to view a copy of this License. If the interface presents a list of - user commands or options, such as a menu, a prominent item in the list - meets this criterion. - - 1. Source Code. - - The “source code” for a work means the preferred form of the work for - making modifications to it. “Object code” means any non-source form of a - work. - - A “Standard Interface” means an interface that either is an official - standard defined by a recognized standards body, or, in the case of - interfaces specified for a particular programming language, one that is - widely used among developers working in that language. The “System - Libraries” of an executable work include anything, other than the work as - a whole, that (a) is included in the normal form of packaging a Major - Component, but which is not part of that Major Component, and (b) serves - only to enable use of the work with that Major Component, or to implement - a Standard Interface for which an implementation is available to the - public in source code form. A “Major Component”, in this context, means a - major essential component (kernel, window system, and so on) of the - specific operating system (if any) on which the executable work runs, or - a compiler used to produce the work, or an object code interpreter used - to run it. - - The “Corresponding Source” for a work in object code form means all the - source code needed to generate, install, and (for an executable work) run - the object code and to modify the work, including scripts to control - those activities. However, it does not include the work's System - Libraries, or general-purpose tools or generally available free programs - which are used unmodified in performing those activities but which are - not part of the work. For example, Corresponding Source includes - interface definition files associated with source files for the work, and - the source code for shared libraries and dynamically linked subprograms - that the work is specifically designed to require, such as by intimate - data communication or control flow between those subprograms and other - parts of the work. - - The Corresponding Source need not include anything that users can - regenerate automatically from other parts of the Corresponding Source. - - The Corresponding Source for a work in source code form is that same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of - copyright on the Program, and are irrevocable provided the stated - conditions are met. This License explicitly affirms your unlimited - permission to run the unmodified Program, subject to section 13. The - output from running a covered work is covered by this License only if the - output, given its content, constitutes a covered work. This License - acknowledges your rights of fair use or other equivalent, as provided by - copyright law. Subject to section 13, you may make, run and propagate - covered works that you do not convey, without conditions so long as your - license otherwise remains in force. You may convey covered works to - others for the sole purpose of having them make modifications exclusively - for you, or provide you with facilities for running those works, provided - that you comply with the terms of this License in conveying all - material for which you do not control copyright. Those thus making or - running the covered works for you must do so exclusively on your - behalf, under your direction and control, on terms that prohibit them - from making any copies of your copyrighted material outside their - relationship with you. - - Conveying under any other circumstances is permitted solely under the - conditions stated below. Sublicensing is not allowed; section 10 makes it - unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological - measure under any applicable law fulfilling obligations under article 11 - of the WIPO copyright treaty adopted on 20 December 1996, or similar laws - prohibiting or restricting circumvention of such measures. - - When you convey a covered work, you waive any legal power to forbid - circumvention of technological measures to the extent such circumvention is - effected by exercising rights under this License with respect to the - covered work, and you disclaim any intention to limit operation or - modification of the work as a means of enforcing, against the work's users, - your or third parties' legal rights to forbid circumvention of - technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you - receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice; keep - intact all notices stating that this License and any non-permissive terms - added in accord with section 7 apply to the code; keep intact all notices - of the absence of any warranty; and give all recipients a copy of this - License along with the Program. You may charge any price or no price for - each copy that you convey, and you may offer support or warranty - protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to - produce it from the Program, in the form of source code under the terms - of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified it, - and giving a relevant date. - - b) The work must carry prominent notices stating that it is released - under this License and any conditions added under section 7. This - requirement modifies the requirement in section 4 to “keep intact all - notices”. - - c) You must license the entire work, as a whole, under this License to - anyone who comes into possession of a copy. This License will therefore - apply, along with any applicable section 7 additional terms, to the - whole of the work, and all its parts, regardless of how they are - packaged. This License gives no permission to license the work in any - other way, but it does not invalidate such permission if you have - separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your work - need not make them do so. - - A compilation of a covered work with other separate and independent - works, which are not by their nature extensions of the covered work, and - which are not combined with it such as to form a larger program, in or on - a volume of a storage or distribution medium, is called an “aggregate” if - the compilation and its resulting copyright are not used to limit the - access or legal rights of the compilation's users beyond what the - individual works permit. Inclusion of a covered work in an aggregate does - not cause this License to apply to the other parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms of - sections 4 and 5, provided that you also convey the machine-readable - Corresponding Source under the terms of this License, in one of these - ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium customarily - used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a written - offer, valid for at least three years and valid for as long as you - offer spare parts or customer support for that product model, to give - anyone who possesses the object code either (1) a copy of the - Corresponding Source for all the software in the product that is - covered by this License, on a durable physical medium customarily used - for software interchange, for a price no more than your reasonable cost - of physically performing this conveying of source, or (2) access to - copy the Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This alternative is - allowed only occasionally and noncommercially, and only if you received - the object code with such an offer, in accord with subsection 6b. - - d) Convey the object code by offering access from a designated place - (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to copy - the object code is a network server, the Corresponding Source may be on - a different server (operated by you or a third party) that supports - equivalent copying facilities, provided you maintain clear directions - next to the object code saying where to find the Corresponding Source. - Regardless of what server hosts the Corresponding Source, you remain - obligated to ensure that it is available for as long as needed to - satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided you - inform other peers where the object code and Corresponding Source of - the work are being offered to the general public at no charge under - subsection 6d. - - A separable portion of the object code, whose source code is excluded - from the Corresponding Source as a System Library, need not be included - in conveying the object code work. - - A “User Product” is either (1) a “consumer product”, which means any - tangible personal property which is normally used for personal, family, - or household purposes, or (2) anything designed or sold for incorporation - into a dwelling. In determining whether a product is a consumer product, - doubtful cases shall be resolved in favor of coverage. For a particular - product received by a particular user, “normally used” refers to a - typical or common use of that class of product, regardless of the status - of the particular user or of the way in which the particular user - actually uses, or expects or is expected to use, the product. A product - is a consumer product regardless of whether the product has substantial - commercial, industrial or non-consumer uses, unless such uses represent - the only significant mode of use of the product. - - “Installation Information” for a User Product means any methods, - procedures, authorization keys, or other information required to install - and execute modified versions of a covered work in that User Product from - a modified version of its Corresponding Source. The information must - suffice to ensure that the continued functioning of the modified object - code is in no case prevented or interfered with solely because - modification has been made. - - If you convey an object code work under this section in, or with, or - specifically for use in, a User Product, and the conveying occurs as part - of a transaction in which the right of possession and use of the User - Product is transferred to the recipient in perpetuity or for a fixed term - (regardless of how the transaction is characterized), the Corresponding - Source conveyed under this section must be accompanied by the - Installation Information. But this requirement does not apply if neither - you nor any third party retains the ability to install modified object - code on the User Product (for example, the work has been installed in - ROM). - - The requirement to provide Installation Information does not include a - requirement to continue to provide support service, warranty, or updates - for a work that has been modified or installed by the recipient, or for - the User Product in which it has been modified or installed. Access - to a network may be denied when the modification itself materially - and adversely affects the operation of the network or violates the - rules and protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, in - accord with this section must be in a format that is publicly documented - (and with an implementation available to the public in source code form), - and must require no special password or key for unpacking, reading or - copying. - - 7. Additional Terms. - - “Additional permissions” are terms that supplement the terms of this - License by making exceptions from one or more of its conditions. - Additional permissions that are applicable to the entire Program shall be - treated as though they were included in this License, to the extent that - they are valid under applicable law. If additional permissions apply only - to part of the Program, that part may be used separately under those - permissions, but the entire Program remains governed by this License - without regard to the additional permissions. When you convey a copy of - a covered work, you may at your option remove any additional permissions - from that copy, or from any part of it. (Additional permissions may be - written to require their own removal in certain cases when you modify the - work.) You may place additional permissions on material, added by you to - a covered work, for which you have or can give appropriate copyright - permission. - - Notwithstanding any other provision of this License, for material you add - to a covered work, you may (if authorized by the copyright holders of - that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some trade - names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that material - by anyone who conveys the material (or modified versions of it) with - contractual assumptions of liability to the recipient, for any - liability that these contractual assumptions directly impose on those - licensors and authors. - - All other non-permissive additional terms are considered “further - restrictions” within the meaning of section 10. If the Program as you - received it, or any part of it, contains a notice stating that it is - governed by this License along with a term that is a further restriction, - you may remove that term. If a license document contains a further - restriction but permits relicensing or conveying under this License, you - may add to a covered work material governed by the terms of that license - document, provided that the further restriction does not survive such - relicensing or conveying. - - If you add terms to a covered work in accord with this section, you must - place, in the relevant source files, a statement of the additional terms - that apply to those files, or a notice indicating where to find the - applicable terms. Additional terms, permissive or non-permissive, may be - stated in the form of a separately written license, or stated as - exceptions; the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly - provided under this License. Any attempt otherwise to propagate or modify - it is void, and will automatically terminate your rights under this - License (including any patent licenses granted under the third paragraph - of section 11). - - However, if you cease all violation of this License, then your license - from a particular copyright holder is reinstated (a) provisionally, - unless and until the copyright holder explicitly and finally terminates - your license, and (b) permanently, if the copyright holder fails to - notify you of the violation by some reasonable means prior to 60 days - after the cessation. - - Moreover, your license from a particular copyright holder is reinstated - permanently if the copyright holder notifies you of the violation by some - reasonable means, this is the first time you have received notice of - violation of this License (for any work) from that copyright holder, and - you cure the violation prior to 30 days after your receipt of the notice. - - Termination of your rights under this section does not terminate the - licenses of parties who have received copies or rights from you under - this License. If your rights have been terminated and not permanently - reinstated, you do not qualify to receive new licenses for the same - material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or run a - copy of the Program. Ancillary propagation of a covered work occurring - solely as a consequence of using peer-to-peer transmission to receive a - copy likewise does not require acceptance. However, nothing other than - this License grants you permission to propagate or modify any covered - work. These actions infringe copyright if you do not accept this License. - Therefore, by modifying or propagating a covered work, you indicate your - acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically receives - a license from the original licensors, to run, modify and propagate that - work, subject to this License. You are not responsible for enforcing - compliance by third parties with this License. - - An “entity transaction” is a transaction transferring control of an - organization, or substantially all assets of one, or subdividing an - organization, or merging organizations. If propagation of a covered work - results from an entity transaction, each party to that transaction who - receives a copy of the work also receives whatever licenses to the work - the party's predecessor in interest had or could give under the previous - paragraph, plus a right to possession of the Corresponding Source of the - work from the predecessor in interest, if the predecessor has it or can - get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the rights - granted or affirmed under this License. For example, you may not impose a - license fee, royalty, or other charge for exercise of rights granted - under this License, and you may not initiate litigation (including a - cross-claim or counterclaim in a lawsuit) alleging that any patent claim - is infringed by making, using, selling, offering for sale, or importing - the Program or any portion of it. - - 11. Patents. - - A “contributor” is a copyright holder who authorizes use under this - License of the Program or a work on which the Program is based. The work - thus licensed is called the contributor's “contributor version”. - - A contributor's “essential patent claims” are all patent claims owned or - controlled by the contributor, whether already acquired or hereafter - acquired, that would be infringed by some manner, permitted by this - License, of making, using, or selling its contributor version, but do not - include claims that would be infringed only as a consequence of further - modification of the contributor version. For purposes of this definition, - “control” includes the right to grant patent sublicenses in a manner - consistent with the requirements of this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free - patent license under the contributor's essential patent claims, to make, - use, sell, offer for sale, import and otherwise run, modify and propagate - the contents of its contributor version. - - In the following three paragraphs, a “patent license” is any express - agreement or commitment, however denominated, not to enforce a patent - (such as an express permission to practice a patent or covenant not to - sue for patent infringement). To “grant” such a patent license to a party - means to make such an agreement or commitment not to enforce a patent - against the party. - - If you convey a covered work, knowingly relying on a patent license, and - the Corresponding Source of the work is not available for anyone to copy, - free of charge and under the terms of this License, through a publicly - available network server or other readily accessible means, then you must - either (1) cause the Corresponding Source to be so available, or (2) - arrange to deprive yourself of the benefit of the patent license for this - particular work, or (3) arrange, in a manner consistent with the - requirements of this License, to extend the patent license to downstream - recipients. “Knowingly relying” means you have actual knowledge that, but - for the patent license, your conveying the covered work in a country, or - your recipient's use of the covered work in a country, would infringe - one or more identifiable patents in that country that you have reason - to believe are valid. - - If, pursuant to or in connection with a single transaction or - arrangement, you convey, or propagate by procuring conveyance of, a - covered work, and grant a patent license to some of the parties receiving - the covered work authorizing them to use, propagate, modify or convey a - specific copy of the covered work, then the patent license you grant is - automatically extended to all recipients of the covered work and works - based on it. - - A patent license is “discriminatory” if it does not include within the - scope of its coverage, prohibits the exercise of, or is conditioned on - the non-exercise of one or more of the rights that are specifically - granted under this License. You may not convey a covered work if you are - a party to an arrangement with a third party that is in the business of - distributing software, under which you make payment to the third party - based on the extent of your activity of conveying the work, and under - which the third party grants, to any of the parties who would receive the - covered work from you, a discriminatory patent license (a) in connection - with copies of the covered work conveyed by you (or copies made from - those copies), or (b) primarily for and in connection with specific - products or compilations that contain the covered work, unless you - entered into that arrangement, or that patent license was granted, prior - to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting any - implied license or other defenses to infringement that may otherwise be - available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot use, - propagate or convey a covered work so as to satisfy simultaneously your - obligations under this License and any other pertinent obligations, then - as a consequence you may not use, propagate or convey it at all. For - example, if you agree to terms that obligate you to collect a royalty for - further conveying from those to whom you convey the Program, the only way - you could satisfy both those terms and this License would be to refrain - entirely from conveying the Program. - - 13. Offering the Program as a Service. - - If you make the functionality of the Program or a modified version - available to third parties as a service, you must make the Service Source - Code available via network download to everyone at no charge, under the - terms of this License. Making the functionality of the Program or - modified version available to third parties as a service includes, - without limitation, enabling third parties to interact with the - functionality of the Program or modified version remotely through a - computer network, offering a service the value of which entirely or - primarily derives from the value of the Program or modified version, or - offering a service that accomplishes for users the primary purpose of the - Program or modified version. - - “Service Source Code” means the Corresponding Source for the Program or - the modified version, and the Corresponding Source for all programs that - you use to make the Program or modified version available as a service, - including, without limitation, management software, user interfaces, - application program interfaces, automation software, monitoring software, - backup software, storage software and hosting software, all such that a - user could run an instance of the service using the Service Source Code - you make available. - - 14. Revised Versions of this License. - - MongoDB, Inc. may publish revised and/or new versions of the Server Side - Public License from time to time. Such new versions will be similar in - spirit to the present version, but may differ in detail to address new - problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies that a certain numbered version of the Server Side Public - License “or any later version” applies to it, you have the option of - following the terms and conditions either of that numbered version or of - any later version published by MongoDB, Inc. If the Program does not - specify a version number of the Server Side Public License, you may - choose any version ever published by MongoDB, Inc. - - If the Program specifies that a proxy can decide which future versions of - the Server Side Public License can be used, that proxy's public statement - of acceptance of a version permanently authorizes you to choose that - version for the Program. - - Later license versions may give you additional or different permissions. - However, no additional obligations are imposed on any author or copyright - holder as a result of your choosing to follow a later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY - APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT - HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY - OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM - IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF - ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS - THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING - ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF - THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO - LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU - OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER - PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided above - cannot be given local legal effect according to their terms, reviewing - courts shall apply local law that most closely approximates an absolute - waiver of all civil liability in connection with the Program, unless a - warranty or assumption of liability accompanies a copy of the Program in - return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 deleted file mode 100644 index 197b2ffd..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README deleted file mode 100644 index 97f1dc72..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README +++ /dev/null @@ -1,87 +0,0 @@ -MongoDB README - -Welcome to MongoDB! - -COMPONENTS - - mongod - The database server. - mongos - Sharding router. - mongo - The database shell (uses interactive javascript). - -UTILITIES - - install_compass - Installs MongoDB Compass for your platform. - -BUILDING - - See docs/building.md. - -RUNNING - - For command line options invoke: - - $ ./mongod --help - - To run a single server database: - - $ sudo mkdir -p /data/db - $ ./mongod - $ - $ # The mongo javascript shell connects to localhost and test database by default: - $ ./mongo - > help - -INSTALLING COMPASS - - You can install compass using the install_compass script packaged with MongoDB: - - $ ./install_compass - - This will download the appropriate MongoDB Compass package for your platform - and install it. - -DRIVERS - - Client drivers for most programming languages are available at - https://docs.mongodb.com/manual/applications/drivers/. Use the shell - ("mongo") for administrative tasks. - -BUG REPORTS - - See https://github.com/mongodb/mongo/wiki/Submit-Bug-Reports. - -PACKAGING - - Packages are created dynamically by the package.py script located in the - buildscripts directory. This will generate RPM and Debian packages. - -DOCUMENTATION - - https://docs.mongodb.com/manual/ - -CLOUD HOSTED MONGODB - - https://www.mongodb.com/cloud/atlas - -FORUMS - - https://community.mongodb.com - - A forum for technical questions about using MongoDB. - - https://community.mongodb.com/c/server-dev - - A forum for technical questions about building and developing MongoDB. - -LEARN MONGODB - - https://university.mongodb.com/ - -LICENSE - - MongoDB is free and open-source. Versions released prior to October 16, - 2018 are published under the AGPL. All versions released after October - 16, 2018, including patch fixes for prior versions, are published under - the Server Side Public License (SSPL) v1. See individual files for - details. - diff --git a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES deleted file mode 100644 index 8c9e17e3..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,1568 +0,0 @@ -MongoDB uses third-party libraries or other resources that may -be distributed under licenses different than the MongoDB software. - -In the event that we accidentally failed to list a required notice, -please bring it to our attention through any of the ways detailed here : - - mongodb-dev@googlegroups.com - -The attached notices are provided for information only. - -For any licenses that require disclosure of source, sources are available at -https://github.com/mongodb/mongo. - - -1) License Notice for Boost ---------------------------- - -http://www.boost.org/LICENSE_1_0.txt - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - -3) License Notice for PCRE --------------------------- - -http://www.pcre.org/licence.txt - -PCRE LICENCE ------------- - -PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - -Release 7 of PCRE is distributed under the terms of the "BSD" licence, as -specified below. The documentation for PCRE, supplied in the "doc" -directory, is distributed under the same terms as the software itself. - -The basic library functions are written in C and are freestanding. Also -included in the distribution is a set of C++ wrapper functions. - - -THE BASIC LIBRARY FUNCTIONS ---------------------------- - -Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk - -University of Cambridge Computing Service, -Cambridge, England. - -Copyright (c) 1997-2008 University of Cambridge -All rights reserved. - - -THE C++ WRAPPER FUNCTIONS -------------------------- - -Contributed by: Google Inc. - -Copyright (c) 2007-2008, Google Inc. -All rights reserved. - - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -4) License notice for Aladdin MD5 ---------------------------------- - -Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -5) License notice for Snappy - http://code.google.com/p/snappy/ ---------------------------------- - Copyright 2005 and onwards Google Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - A light-weight compression algorithm. It is designed for speed of - compression and decompression, rather than for the utmost in space - savings. - - For getting better compression ratios when you are compressing data - with long repeated sequences or compressing data that is similar to - other data, while still compressing fast, you might look at first - using BMDiff and then compressing the output of BMDiff with - Snappy. - -6) License notice for Google Perftools (TCMalloc utility) ---------------------------------- -New BSD License - -Copyright (c) 1998-2006, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -7) License notice for Linenoise -------------------------------- - - Copyright (c) 2010, Salvatore Sanfilippo - Copyright (c) 2010, Pieter Noordhuis - - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -8) License notice for S2 Geometry Library ------------------------------------------ - Copyright 2005 Google Inc. All Rights Reserved. - - 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. - -9) License notice for MurmurHash --------------------------------- - - Copyright (c) 2010-2012 Austin Appleby - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -10) License notice for Snowball - Copyright (c) 2001, Dr Martin Porter - All rights reserved. - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -11) License notice for yaml-cpp -------------------------------- - -Copyright (c) 2008 Jesse Beder. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -12) License notice for zlib ---------------------------- - -http://www.zlib.net/zlib_license.html - -zlib.h -- interface of the 'zlib' general purpose compression library -version 1.2.8, April 28th, 2013 - -Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -13) License notice for 3rd party software included in the WiredTiger library ----------------------------------------------------------------------------- - -http://source.wiredtiger.com/license.html - -WiredTiger Distribution Files | Copyright Holder | License ------------------------------ | ----------------------------------- | ---------------------- -src/include/bitstring.i | University of California, Berkeley | BSD-3-Clause License -src/include/queue.h | University of California, Berkeley | BSD-3-Clause License -src/os_posix/os_getopt.c | University of California, Berkeley | BSD-3-Clause License -src/support/hash_city.c | Google, Inc. | The MIT License -src/support/hash_fnv.c | Authors | Public Domain - - -Other optional 3rd party software included in the WiredTiger distribution is removed by MongoDB. - - -BSD-3-CLAUSE LICENSE --------------------- - -http://www.opensource.org/licenses/BSD-3-Clause - -Copyright (c) 1987, 1989, 1991, 1993, 1994 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - - -THE MIT LICENSE ---------------- - -http://www.opensource.org/licenses/MIT - -Copyright (c) 2011 Google, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -14) License Notice for SpiderMonkey ------------------------------------ - -|------------------------------------------------|------------------|---------------| -| SpiderMonkey Distribution Files | Copyright Holder | License | -|------------------------------------------------|------------------|---------------| -| js/src/jit/shared/AssemblerBuffer-x86-shared.h | Apple, Inc | BSD-2-Clause | -| js/src/jit/shared/BaseAssembler-x86-shared.h | | | -|------------------------------------------------|------------------|---------------| -| js/src/builtin/ | Google, Inc | BSD-3-Clause | -| js/src/irregexp/ | | | -| js/src/jit/arm/ | | | -| js/src/jit/mips/ | | | -| mfbt/double-conversion/ | | | -|------------------------------------------------|------------------|---------------| -| intl/icu/source/common/unicode/ | IBM, Inc | ICU | -|------------------------------------------------|------------------|---------------| -| js/src/asmjs/ | Mozilla, Inc | Apache2 | -|------------------------------------------------|------------------|---------------| -| js/public/ | Mozilla, Inc | MPL2 | -| js/src/ | | | -| mfbt | | | -|------------------------------------------------|------------------|---------------| -| js/src/vm/Unicode.cpp | None | Public Domain | -|------------------------------------------------|------------------|---------------| -| mfbt/lz4.c | Yann Collet | BSD-2-Clause | -| mfbt/lz4.h | | | -|------------------------------------------------|------------------|---------------| - -Other optional 3rd party software included in the SpiderMonkey distribution is removed by MongoDB. - - -Apple, Inc: BSD-2-Clause ------------------------- - -Copyright (C) 2008 Apple Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Google, Inc: BSD-3-Clause -------------------------- - -Copyright 2012 the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -ICU License - ICU 1.8.1 and later ---------------------------------- - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2012 International Business Machines Corporation and -others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, provided that the above copyright notice(s) and this -permission notice appear in all copies of the Software and that both the -above copyright notice(s) and this permission notice appear in supporting -documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE -BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization of the -copyright holder. - -All trademarks and registered trademarks mentioned herein are the property -of their respective owners. - - -Mozilla, Inc: Apache 2 ----------------------- - -Copyright 2014 Mozilla Foundation - -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. - - -Mozilla, Inc: MPL 2 -------------------- - -Copyright 2014 Mozilla Foundation - -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -Public Domain -------------- - -Any copyright is dedicated to the Public Domain. -http://creativecommons.org/licenses/publicdomain/ - - -LZ4: BSD-2-Clause ------------------ - -Copyright (C) 2011-2014, Yann Collet. -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 source repository : http://code.google.com/p/lz4/ -- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c - -15) License Notice for Intel DFP Math Library ---------------------------------------------- - -Copyright (c) 2011, Intel Corp. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - his list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -16) License Notice for Unicode Data ------------------------------------ - -Copyright © 1991-2015 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -17 ) License Notice for Valgrind.h ----------------------------------- - ----------------------------------------------------------------- - -Notice that the following BSD-style license applies to this one -file (valgrind.h) only. The rest of Valgrind is licensed under the -terms of the GNU General Public License, version 2, unless -otherwise indicated. See the COPYING file in the source -distribution for details. - ----------------------------------------------------------------- - -This file is part of Valgrind, a dynamic binary instrumentation -framework. - -Copyright (C) 2000-2015 Julian Seward. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - -4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------- - -Notice that the above BSD-style license applies to this one file -(valgrind.h) only. The entire rest of Valgrind is licensed under -the terms of the GNU General Public License, version 2. See the -COPYING file in the source distribution for details. - ----------------------------------------------------------------- - -18) License notice for ICU4C ----------------------------- - -ICU License - ICU 1.8.1 and later - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2016 International Business Machines Corporation and others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY -SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER -RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - - -All trademarks and registered trademarks mentioned herein are the -property of their respective owners. - ---------------------- - -Third-Party Software Licenses - -This section contains third-party software notices and/or additional -terms for licensed third-party software components included within ICU -libraries. - -1. Unicode Data Files and Software - -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2016 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) - - # The Google Chrome software developed by Google is licensed under - # the BSD license. Other software included in this distribution is - # provided under other licenses, as set forth below. - # - # The BSD License - # http://opensource.org/licenses/bsd-license.php - # Copyright (C) 2006-2008, Google Inc. - # - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided with - # the distribution. - # Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - # - # The word list in cjdict.txt are generated by combining three word lists - # listed below with further processing for compound word breaking. The - # frequency is generated with an iterative training against Google web - # corpora. - # - # * Libtabe (Chinese) - # - https://sourceforge.net/project/?group_id=1519 - # - Its license terms and conditions are shown below. - # - # * IPADIC (Japanese) - # - http://chasen.aist-nara.ac.jp/chasen/distribution.html - # - Its license terms and conditions are shown below. - # - # ---------COPYING.libtabe ---- BEGIN-------------------- - # - # /* - # * Copyrighy (c) 1999 TaBE Project. - # * Copyright (c) 1999 Pai-Hsiang Hsiao. - # * All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the TaBE Project nor the names of its - # * contributors may be used to endorse or promote products derived - # * from this software without specific prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # /* - # * Copyright (c) 1999 Computer Systems and Communication Lab, - # * Institute of Information Science, Academia - # * Sinica. All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the Computer Systems and Communication Lab - # * nor the names of its contributors may be used to endorse or - # * promote products derived from this software without specific - # * prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, - # University of Illinois - # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 - # - # ---------------COPYING.libtabe-----END-------------------------------- - # - # - # ---------------COPYING.ipadic-----BEGIN------------------------------- - # - # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science - # and Technology. All Rights Reserved. - # - # Use, reproduction, and distribution of this software is permitted. - # Any copy of this software, whether in its original form or modified, - # must include both the above copyright notice and the following - # paragraphs. - # - # Nara Institute of Science and Technology (NAIST), - # the copyright holders, disclaims all warranties with regard to this - # software, including all implied warranties of merchantability and - # fitness, in no event shall NAIST be liable for - # any special, indirect or consequential damages or any damages - # whatsoever resulting from loss of use, data or profits, whether in an - # action of contract, negligence or other tortuous action, arising out - # of or in connection with the use or performance of this software. - # - # A large portion of the dictionary entries - # originate from ICOT Free Software. The following conditions for ICOT - # Free Software applies to the current dictionary as well. - # - # Each User may also freely distribute the Program, whether in its - # original form or modified, to any third party or parties, PROVIDED - # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear - # on, or be attached to, the Program, which is distributed substantially - # in the same form as set out herein and that such intended - # distribution, if actually made, will neither violate or otherwise - # contravene any of the laws and regulations of the countries having - # jurisdiction over the User or the intended distribution itself. - # - # NO WARRANTY - # - # The program was produced on an experimental basis in the course of the - # research and development conducted during the project and is provided - # to users as so produced on an experimental basis. Accordingly, the - # program is provided without any warranty whatsoever, whether express, - # implied, statutory or otherwise. The term "warranty" used herein - # includes, but is not limited to, any warranty of the quality, - # performance, merchantability and fitness for a particular purpose of - # the program and the nonexistence of any infringement or violation of - # any right of any third party. - # - # Each user of the program will agree and understand, and be deemed to - # have agreed and understood, that there is no warranty whatsoever for - # the program and, accordingly, the entire risk arising from or - # otherwise connected with the program is assumed by the user. - # - # Therefore, neither ICOT, the copyright holder, or any other - # organization that participated in or was otherwise related to the - # development of the program and their respective officials, directors, - # officers and other employees shall be held liable for any and all - # damages, including, without limitation, general, special, incidental - # and consequential damages, arising out of or otherwise in connection - # with the use or inability to use the program or any product, material - # or result produced or otherwise obtained by using the program, - # regardless of whether they have been advised of, or otherwise had - # knowledge of, the possibility of such damages at any time during the - # project or thereafter. Each user will be deemed to have agreed to the - # foregoing by his or her commencement of use of the program. The term - # "use" as used herein includes, but is not limited to, the use, - # modification, copying and distribution of the program and the - # production of secondary products from the program. - # - # In the case where the program, whether in its original form or - # modified, was distributed or delivered to or received by a user from - # any person, organization or entity other than ICOT, unless it makes or - # grants independently of ICOT any specific warranty to the user in - # writing, such person, organization or entity, will also be exempted - # from and not be held liable to the user for any such damages as noted - # above as far as the program is concerned. - # - # ---------------COPYING.ipadic-----END---------------------------------- - -3. Lao Word Break Dictionary Data (laodict.txt) - - # Copyright (c) 2013 International Business Machines Corporation - # and others. All Rights Reserved. - # - # Project: http://code.google.com/p/lao-dictionary/ - # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt - # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt - # (copied below) - # - # This file is derived from the above dictionary, with slight - # modifications. - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, - # are permitted provided that the following conditions are met: - # - # - # Redistributions of source code must retain the above copyright notice, this - # list of conditions and the following disclaimer. Redistributions in - # binary form must reproduce the above copyright notice, this list of - # conditions and the following disclaimer in the documentation and/or - # other materials provided with the distribution. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # OF THE POSSIBILITY OF SUCH DAMAGE. - # -------------------------------------------------------------------------- - -4. Burmese Word Break Dictionary Data (burmesedict.txt) - - # Copyright (c) 2014 International Business Machines Corporation - # and others. All Rights Reserved. - # - # This list is part of a project hosted at: - # github.com/kanyawtech/myanmar-karen-word-lists - # - # -------------------------------------------------------------------------- - # Copyright (c) 2013, LeRoy Benjamin Sharon - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: Redistributions of source code must retain the above - # copyright notice, this list of conditions and the following - # disclaimer. Redistributions in binary form must reproduce the - # above copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided - # with the distribution. - # - # Neither the name Myanmar Karen Word Lists, nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - # -------------------------------------------------------------------------- - -5. Time Zone Database - - ICU uses the public domain data and code derived from Time Zone -Database for its time zone support. The ownership of the TZ database -is explained in BCP 175: Procedure for Maintaining the Time Zone -Database section 7. - - # 7. Database Ownership - # - # The TZ database itself is not an IETF Contribution or an IETF - # document. Rather it is a pre-existing and regularly updated work - # that is in the public domain, and is intended to remain in the - # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do - # not apply to the TZ Database or contributions that individuals make - # to it. Should any claims be made and substantiated against the TZ - # Database, the organization that is providing the IANA - # Considerations defined in this RFC, under the memorandum of - # understanding with the IETF, currently ICANN, may act in accordance - # with all competent court orders. No ownership claims will be made - # by ICANN or the IETF Trust on the database or the code. Any person - # making a contribution to the database or code waives all rights to - # future claims in that contribution or in the TZ Database. - -19) License notice for timelib ------------------------------- - -The MIT License (MIT) - -Copyright (c) 2015-2017 Derick Rethans -Copyright (c) 2017 MongoDB, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -20) License notice for windows dirent implementation ----------------------------------------------------- - - * Dirent interface for Microsoft Visual Studio - * Version 1.21 - * - * Copyright (C) 2006-2012 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - - - 21) License notice for abseil-cpp ----------------------------- - - Copyright (c) Google Inc. - - 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. - - 22) License notice for Zstandard ----------------------------- - - BSD License - - For Zstandard software - - Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 23) License notice for ASIO ----------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 24) License notice for MPark.Variant -------------------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 25) License notice for fmt ---------------------------- - -Copyright (c) 2012 - present, Victor Zverovich -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 26) License notice for SafeInt ---------------------------- - -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. - -MIT License - -Copyright (c) 2018 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - 27) License Notice for Raft TLA+ Specification ------------------------------------------------ - -https://github.com/ongardie/dissertation/blob/master/LICENSE - -Copyright 2014 Diego Ongaro. - -Some of our TLA+ specifications are based on the Raft TLA+ specification by Diego Ongaro. - -End diff --git a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md deleted file mode 100644 index 550ae4ed..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2014 MongoDB, Inc. - -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/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md deleted file mode 100644 index e60e0cd0..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md +++ /dev/null @@ -1,72 +0,0 @@ -MongoDB Tools -=================================== - - - **bsondump** - _display BSON files in a human-readable format_ - - **mongoimport** - _Convert data from JSON, TSV or CSV and insert them into a collection_ - - **mongoexport** - _Write an existing collection to CSV or JSON format_ - - **mongodump/mongorestore** - _Dump MongoDB backups to disk in .BSON format, or restore them to a live database_ - - **mongostat** - _Monitor live MongoDB servers, replica sets, or sharded clusters_ - - **mongofiles** - _Read, write, delete, or update files in [GridFS](http://docs.mongodb.org/manual/core/gridfs/)_ - - **mongotop** - _Monitor read/write activity on a mongo server_ - - -Report any bugs, improvements, or new feature requests at https://jira.mongodb.org/browse/TOOLS - -Building Tools ---------------- - -We currently build the tools with Go version 1.15. Other Go versions may work but they are untested. - -Using `go get` to directly build the tools will not work. To build them, it's recommended to first clone this repository: - -``` -git clone https://github.com/mongodb/mongo-tools -cd mongo-tools -``` - -Then run `./make build` to build all the tools, placing them in the `bin` directory inside the repository. - -You can also build a subset of the tools using the `-tools` option. For example, `./make build -tools=mongodump,mongorestore` builds only `mongodump` and `mongorestore`. - -To use the build/test scripts in this repository, you **_must_** set GOROOT to your Go root directory. This may depend on how you installed Go. - -``` -export GOROOT=/usr/local/go -``` - -Updating Dependencies ---------------- -Starting with version 100.3.1, the tools use `go mod` to manage dependencies. All dependencies are listed in the `go.mod` file and are directly vendored in the `vendor` directory. - -In order to make changes to dependencies, you first need to change the `go.mod` file. You can manually edit that file to add/update/remove entries, or you can run the following in the repository directory: - -``` -go mod edit -require=@ # for adding or updating a dependency -go mod edit -droprequire= # for removing a dependency -``` - -Then run `go mod vendor -v` to reconstruct the `vendor` directory to match the changed `go.mod` file. - -Optionally, run `go mod tidy -v` to ensure that the `go.mod` file matches the `mongo-tools` source code. - -Contributing ---------------- -See our [Contributor's Guide](CONTRIBUTING.md). - -Documentation ---------------- -See the MongoDB packages [documentation](https://docs.mongodb.org/database-tools/). - -For documentation on older versions of the MongoDB, reference that version of the [MongoDB Server Manual](docs.mongodb.com/manual): - -- [MongoDB 4.2 Tools](https://docs.mongodb.org/v4.2/reference/program) -- [MongoDB 4.0 Tools](https://docs.mongodb.org/v4.0/reference/program) -- [MongoDB 3.6 Tools](https://docs.mongodb.org/v3.6/reference/program) - -Adding New Platforms Support ---------------- -See our [Adding New Platform Support Guide](PLATFORMSUPPORT.md). - -Vendoring the Change into Server Repo ---------------- -See our [Vendor the Change into Server Repo](SERVERVENDORING.md). diff --git a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES b/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES deleted file mode 100644 index 3d75e64b..00000000 --- a/Mongo2Go-4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,3319 +0,0 @@ ---------------------------------------------------------------------- -License notice for hashicorp/go-rootcerts ---------------------------------------------------------------------- - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - ---------------------------------------------------------------------- -License notice for JSON and CSV code from github.com/golang/go ---------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/escaper ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Lucas Morales - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo/bson ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/openssl ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/3rf/mongo-lint ----------------------------------------------------------------------- - -Copyright (c) 2013 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/go-stack/stack ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Chris Hines - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/golang/snappy ----------------------------------------------------------------------- - -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/google/gopacket ----------------------------------------------------------------------- - -Copyright (c) 2012 Google, Inc. All rights reserved. -Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Andreas Krennmair, Google, nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/gopherjs/gopherjs ----------------------------------------------------------------------- - -Copyright (c) 2013 Richard Musiol. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/howeyc/gopass ----------------------------------------------------------------------- - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/jessevdk/go-flags ----------------------------------------------------------------------- - -Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/jtolds/gls ----------------------------------------------------------------------- - -Copyright (c) 2013, Space Monkey, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mattn/go-runewidth ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mongodb/mongo-go-driver ----------------------------------------------------------------------- - - 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. - ----------------------------------------------------------------------- -License notice for github.com/nsf/termbox-go ----------------------------------------------------------------------- - -Copyright (C) 2012 termbox-go authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/patrickmn/go-cache ----------------------------------------------------------------------- - -Copyright (c) 2012-2015 Patrick Mylund Nielsen and the go-cache contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions ----------------------------------------------------------------------- - -Copyright (c) 2015 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/go-render ----------------------------------------------------------------------- - -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglematchers ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglemock ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/ogletest ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/reqtrace ----------------------------------------------------------------------- - - 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. - - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey ----------------------------------------------------------------------- - -Copyright (c) 2014 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey/web/client/resources/fonts/Open_Sans ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/spacemonkeygo/spacelog ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/scram ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/stringprep ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/youmark/pkcs8 ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 youmark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for golang.org/x/crypto ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/sync ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/text ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for gopkg.in/tomb.v2 ----------------------------------------------------------------------- - -tomb - support for clean goroutine termination in Go. - -Copyright (c) 2010-2011 - Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Mongo2Go.4.1.0/.signature.p7s b/Mongo2Go.4.1.0/.signature.p7s deleted file mode 100644 index 395978090ae8698047e5bcccb86564a07debc226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12927 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 F{{ys`(g^?n diff --git a/Mongo2Go.4.1.0/Mongo2Go.nuspec b/Mongo2Go.4.1.0/Mongo2Go.nuspec deleted file mode 100644 index f6e628d4..00000000 --- a/Mongo2Go.4.1.0/Mongo2Go.nuspec +++ /dev/null @@ -1,46 +0,0 @@ - - - - Mongo2Go - 4.1.0 - Johannes Hoppe and many contributors - MIT - https://licenses.nuget.org/MIT - icon.png - https://github.com/Mongo2Go/Mongo2Go - Mongo2Go is a managed wrapper around MongoDB binaries. It targets .NET Framework 4.7.2 and .NET Standard 2.1. -This Nuget package contains the executables of mongod, mongoimport and mongoexport v4.4.4 for Windows, Linux and macOS. - - -Mongo2Go has two use cases: - -1. Providing multiple, temporary and isolated MongoDB databases for integration tests -2. Providing a quick to set up MongoDB database for a local developer environment - https://github.com/Mongo2Go/Mongo2Go/releases - Copyright © 2012-2025 Johannes Hoppe and many ❤️ contributors - MongoDB Mongo unit test integration runner - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Mongo2Go.4.1.0/[Content_Types].xml b/Mongo2Go.4.1.0/[Content_Types].xml deleted file mode 100644 index eac33e7f..00000000 --- a/Mongo2Go.4.1.0/[Content_Types].xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Mongo2Go.4.1.0/_rels/.rels b/Mongo2Go.4.1.0/_rels/.rels deleted file mode 100644 index 1a91feb8..00000000 --- a/Mongo2Go.4.1.0/_rels/.rels +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/Mongo2Go.4.1.0/icon.png b/Mongo2Go.4.1.0/icon.png deleted file mode 100644 index 23750b60b217997121d919c0489c75e17dcc3b20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 21563 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 yzIsDyUkv>`BR+xgrPRDqGh`C?9fy8?%6 - - - Mongo2Go - - - -

- Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - - - - - Returns and reserves a new port - - - - - Returns the if it is verified that it does not contain any mongod argument already defined by Mongo2Go. - - mongod arguments defined by Mongo2Go - Additional mongod arguments - contains at least one mongod argument already defined by Mongo2Go - A string with the additional mongod arguments - - - - Starts a new process. Process can be killed - - - - - Starts a new process. - - - - - Input File: Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - - - - - Output File: Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - - - - - Structure of a log generated by mongod. Used to deserialize the logs - and pass them to an ILogger. - See: https://docs.mongodb.com/manual/reference/log-messages/#json-log-output-format - Note: "truncated" and "size" are not parsed as we're unsure how to - properly parse and use them. - - - - - Severity of the logs as defined by MongoDB. Mapped to LogLevel - as defined by Microsoft. - D1-D2 mapped to Debug level. D3-D5 mapped Trace level. - - - - - Intention: port numbers won't be assigned twice to avoid connection problems with integration tests - - - - - Returns and reserves a new port - - - - - Reads from Output stream to determine if process is ready - - - - - Send the mongod process logs to .NET's console and debug outputs. - - - - - - Parses and redirects mongod logs to ILogger. - - - - - - - saves about 40 keystrokes - - - - - Populates the template using the provided arguments and the invariant culture - - - - - Populates the template using the provided arguments using the provided formatter - - - - - Mongo2Go main entry point - - - - - State of the current MongoDB instance - - - - - Connections string that should be used to establish a connection the MongoDB instance - - - - - Starts Multiple MongoDB instances with each call - On dispose: kills them and deletes their data directory - - (Optional) If null, mongod logs are wired to .NET's Console and Debug output (provided you haven't added the --quiet additional argument). - If not null, mongod logs are parsed and wired to the provided logger. - Should be used for integration tests - - - - !!! - This method is only used for an internal unit test. Use MongoDbRunner.Start() instead. - But if you find it to be useful (eg. to change every aspect on your own) feel free to implement the interfaces on your own! - - see https://github.com/Mongo2Go/Mongo2Go/issues/41 - - - - Only starts one single MongoDB instance (even on multiple calls), does not kill it, does not delete data - - - Should be used for local debugging only - WARNING: one single instance on one single machine is not a suitable setup for productive environments!!! - - - - - !!! - This method is only used for an internal unit test. Use MongoDbRunner.StartForDebugging() instead. - But if you find it to be useful (eg. to change every aspect on your own) feel free to implement the interfaces on your own! - - see https://github.com/Mongo2Go/Mongo2Go/issues/41 - - - - Executes Mongoimport on the associated MongoDB Instace - - - - - Executes Mongoexport on the associated MongoDB Instace - - - - - usage: local debugging - - - - - usage: integration tests - - - - diff --git a/Mongo2Go.4.1.0/lib/netstandard2.1/Mongo2Go.xml b/Mongo2Go.4.1.0/lib/netstandard2.1/Mongo2Go.xml deleted file mode 100644 index 67d0b4d0..00000000 --- a/Mongo2Go.4.1.0/lib/netstandard2.1/Mongo2Go.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - Mongo2Go - - - - - Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - - - - - Returns and reserves a new port - - - - - Returns the if it is verified that it does not contain any mongod argument already defined by Mongo2Go. - - mongod arguments defined by Mongo2Go - Additional mongod arguments - contains at least one mongod argument already defined by Mongo2Go - A string with the additional mongod arguments - - - - Starts a new process. Process can be killed - - - - - Starts a new process. - - - - - Input File: Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - - - - - Output File: Absolute path stays unchanged, relative path will be relative to current executing directory (usually the /bin folder) - - - - - Structure of a log generated by mongod. Used to deserialize the logs - and pass them to an ILogger. - See: https://docs.mongodb.com/manual/reference/log-messages/#json-log-output-format - Note: "truncated" and "size" are not parsed as we're unsure how to - properly parse and use them. - - - - - Severity of the logs as defined by MongoDB. Mapped to LogLevel - as defined by Microsoft. - D1-D2 mapped to Debug level. D3-D5 mapped Trace level. - - - - - Intention: port numbers won't be assigned twice to avoid connection problems with integration tests - - - - - Returns and reserves a new port - - - - - Reads from Output stream to determine if process is ready - - - - - Send the mongod process logs to .NET's console and debug outputs. - - - - - - Parses and redirects mongod logs to ILogger. - - - - - - - saves about 40 keystrokes - - - - - Populates the template using the provided arguments and the invariant culture - - - - - Populates the template using the provided arguments using the provided formatter - - - - - Mongo2Go main entry point - - - - - State of the current MongoDB instance - - - - - Connections string that should be used to establish a connection the MongoDB instance - - - - - Starts Multiple MongoDB instances with each call - On dispose: kills them and deletes their data directory - - (Optional) If null, mongod logs are wired to .NET's Console and Debug output (provided you haven't added the --quiet additional argument). - If not null, mongod logs are parsed and wired to the provided logger. - Should be used for integration tests - - - - !!! - This method is only used for an internal unit test. Use MongoDbRunner.Start() instead. - But if you find it to be useful (eg. to change every aspect on your own) feel free to implement the interfaces on your own! - - see https://github.com/Mongo2Go/Mongo2Go/issues/41 - - - - Only starts one single MongoDB instance (even on multiple calls), does not kill it, does not delete data - - - Should be used for local debugging only - WARNING: one single instance on one single machine is not a suitable setup for productive environments!!! - - - - - !!! - This method is only used for an internal unit test. Use MongoDbRunner.StartForDebugging() instead. - But if you find it to be useful (eg. to change every aspect on your own) feel free to implement the interfaces on your own! - - see https://github.com/Mongo2Go/Mongo2Go/issues/41 - - - - Executes Mongoimport on the associated MongoDB Instace - - - - - Executes Mongoexport on the associated MongoDB Instace - - - - - usage: local debugging - - - - - usage: integration tests - - - - diff --git a/Mongo2Go.4.1.0/package/services/metadata/core-properties/002438390f9b42fb9cd0a8f5b12ea55f.psmdcp b/Mongo2Go.4.1.0/package/services/metadata/core-properties/002438390f9b42fb9cd0a8f5b12ea55f.psmdcp deleted file mode 100644 index 62e65722..00000000 --- a/Mongo2Go.4.1.0/package/services/metadata/core-properties/002438390f9b42fb9cd0a8f5b12ea55f.psmdcp +++ /dev/null @@ -1,16 +0,0 @@ - - - Johannes Hoppe and many contributors - Mongo2Go is a managed wrapper around MongoDB binaries. It targets .NET Framework 4.7.2 and .NET Standard 2.1. -This Nuget package contains the executables of mongod, mongoimport and mongoexport v4.4.4 for Windows, Linux and macOS. - - -Mongo2Go has two use cases: - -1. Providing multiple, temporary and isolated MongoDB databases for integration tests -2. Providing a quick to set up MongoDB database for a local developer environment - Mongo2Go - 4.1.0 - MongoDB Mongo unit test integration runner - NuGet.Build.Tasks.Pack, Version=6.11.1.2, Culture=neutral, PublicKeyToken=31bf3856ad364e35;.NET Standard 2.0 - \ No newline at end of file diff --git a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt deleted file mode 100644 index b01add13..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt +++ /dev/null @@ -1,557 +0,0 @@ - Server Side Public License - VERSION 1, OCTOBER 16, 2018 - - Copyright © 2018 MongoDB, Inc. - - Everyone is permitted to copy and distribute verbatim copies of this - license document, but changing it is not allowed. - - TERMS AND CONDITIONS - - 0. Definitions. - - “This License” refers to Server Side Public License. - - “Copyright” also means copyright-like laws that apply to other kinds of - works, such as semiconductor masks. - - “The Program” refers to any copyrightable work licensed under this - License. Each licensee is addressed as “you”. “Licensees” and - “recipients” may be individuals or organizations. - - To “modify” a work means to copy from or adapt all or part of the work in - a fashion requiring copyright permission, other than the making of an - exact copy. The resulting work is called a “modified version” of the - earlier work or a work “based on” the earlier work. - - A “covered work” means either the unmodified Program or a work based on - the Program. - - To “propagate” a work means to do anything with it that, without - permission, would make you directly or secondarily liable for - infringement under applicable copyright law, except executing it on a - computer or modifying a private copy. Propagation includes copying, - distribution (with or without modification), making available to the - public, and in some countries other activities as well. - - To “convey” a work means any kind of propagation that enables other - parties to make or receive copies. Mere interaction with a user through a - computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays “Appropriate Legal Notices” to the - extent that it includes a convenient and prominently visible feature that - (1) displays an appropriate copyright notice, and (2) tells the user that - there is no warranty for the work (except to the extent that warranties - are provided), that licensees may convey the work under this License, and - how to view a copy of this License. If the interface presents a list of - user commands or options, such as a menu, a prominent item in the list - meets this criterion. - - 1. Source Code. - - The “source code” for a work means the preferred form of the work for - making modifications to it. “Object code” means any non-source form of a - work. - - A “Standard Interface” means an interface that either is an official - standard defined by a recognized standards body, or, in the case of - interfaces specified for a particular programming language, one that is - widely used among developers working in that language. The “System - Libraries” of an executable work include anything, other than the work as - a whole, that (a) is included in the normal form of packaging a Major - Component, but which is not part of that Major Component, and (b) serves - only to enable use of the work with that Major Component, or to implement - a Standard Interface for which an implementation is available to the - public in source code form. A “Major Component”, in this context, means a - major essential component (kernel, window system, and so on) of the - specific operating system (if any) on which the executable work runs, or - a compiler used to produce the work, or an object code interpreter used - to run it. - - The “Corresponding Source” for a work in object code form means all the - source code needed to generate, install, and (for an executable work) run - the object code and to modify the work, including scripts to control - those activities. However, it does not include the work's System - Libraries, or general-purpose tools or generally available free programs - which are used unmodified in performing those activities but which are - not part of the work. For example, Corresponding Source includes - interface definition files associated with source files for the work, and - the source code for shared libraries and dynamically linked subprograms - that the work is specifically designed to require, such as by intimate - data communication or control flow between those subprograms and other - parts of the work. - - The Corresponding Source need not include anything that users can - regenerate automatically from other parts of the Corresponding Source. - - The Corresponding Source for a work in source code form is that same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of - copyright on the Program, and are irrevocable provided the stated - conditions are met. This License explicitly affirms your unlimited - permission to run the unmodified Program, subject to section 13. The - output from running a covered work is covered by this License only if the - output, given its content, constitutes a covered work. This License - acknowledges your rights of fair use or other equivalent, as provided by - copyright law. Subject to section 13, you may make, run and propagate - covered works that you do not convey, without conditions so long as your - license otherwise remains in force. You may convey covered works to - others for the sole purpose of having them make modifications exclusively - for you, or provide you with facilities for running those works, provided - that you comply with the terms of this License in conveying all - material for which you do not control copyright. Those thus making or - running the covered works for you must do so exclusively on your - behalf, under your direction and control, on terms that prohibit them - from making any copies of your copyrighted material outside their - relationship with you. - - Conveying under any other circumstances is permitted solely under the - conditions stated below. Sublicensing is not allowed; section 10 makes it - unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological - measure under any applicable law fulfilling obligations under article 11 - of the WIPO copyright treaty adopted on 20 December 1996, or similar laws - prohibiting or restricting circumvention of such measures. - - When you convey a covered work, you waive any legal power to forbid - circumvention of technological measures to the extent such circumvention is - effected by exercising rights under this License with respect to the - covered work, and you disclaim any intention to limit operation or - modification of the work as a means of enforcing, against the work's users, - your or third parties' legal rights to forbid circumvention of - technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you - receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice; keep - intact all notices stating that this License and any non-permissive terms - added in accord with section 7 apply to the code; keep intact all notices - of the absence of any warranty; and give all recipients a copy of this - License along with the Program. You may charge any price or no price for - each copy that you convey, and you may offer support or warranty - protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to - produce it from the Program, in the form of source code under the terms - of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified it, - and giving a relevant date. - - b) The work must carry prominent notices stating that it is released - under this License and any conditions added under section 7. This - requirement modifies the requirement in section 4 to “keep intact all - notices”. - - c) You must license the entire work, as a whole, under this License to - anyone who comes into possession of a copy. This License will therefore - apply, along with any applicable section 7 additional terms, to the - whole of the work, and all its parts, regardless of how they are - packaged. This License gives no permission to license the work in any - other way, but it does not invalidate such permission if you have - separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your work - need not make them do so. - - A compilation of a covered work with other separate and independent - works, which are not by their nature extensions of the covered work, and - which are not combined with it such as to form a larger program, in or on - a volume of a storage or distribution medium, is called an “aggregate” if - the compilation and its resulting copyright are not used to limit the - access or legal rights of the compilation's users beyond what the - individual works permit. Inclusion of a covered work in an aggregate does - not cause this License to apply to the other parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms of - sections 4 and 5, provided that you also convey the machine-readable - Corresponding Source under the terms of this License, in one of these - ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium customarily - used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a written - offer, valid for at least three years and valid for as long as you - offer spare parts or customer support for that product model, to give - anyone who possesses the object code either (1) a copy of the - Corresponding Source for all the software in the product that is - covered by this License, on a durable physical medium customarily used - for software interchange, for a price no more than your reasonable cost - of physically performing this conveying of source, or (2) access to - copy the Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This alternative is - allowed only occasionally and noncommercially, and only if you received - the object code with such an offer, in accord with subsection 6b. - - d) Convey the object code by offering access from a designated place - (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to copy - the object code is a network server, the Corresponding Source may be on - a different server (operated by you or a third party) that supports - equivalent copying facilities, provided you maintain clear directions - next to the object code saying where to find the Corresponding Source. - Regardless of what server hosts the Corresponding Source, you remain - obligated to ensure that it is available for as long as needed to - satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided you - inform other peers where the object code and Corresponding Source of - the work are being offered to the general public at no charge under - subsection 6d. - - A separable portion of the object code, whose source code is excluded - from the Corresponding Source as a System Library, need not be included - in conveying the object code work. - - A “User Product” is either (1) a “consumer product”, which means any - tangible personal property which is normally used for personal, family, - or household purposes, or (2) anything designed or sold for incorporation - into a dwelling. In determining whether a product is a consumer product, - doubtful cases shall be resolved in favor of coverage. For a particular - product received by a particular user, “normally used” refers to a - typical or common use of that class of product, regardless of the status - of the particular user or of the way in which the particular user - actually uses, or expects or is expected to use, the product. A product - is a consumer product regardless of whether the product has substantial - commercial, industrial or non-consumer uses, unless such uses represent - the only significant mode of use of the product. - - “Installation Information” for a User Product means any methods, - procedures, authorization keys, or other information required to install - and execute modified versions of a covered work in that User Product from - a modified version of its Corresponding Source. The information must - suffice to ensure that the continued functioning of the modified object - code is in no case prevented or interfered with solely because - modification has been made. - - If you convey an object code work under this section in, or with, or - specifically for use in, a User Product, and the conveying occurs as part - of a transaction in which the right of possession and use of the User - Product is transferred to the recipient in perpetuity or for a fixed term - (regardless of how the transaction is characterized), the Corresponding - Source conveyed under this section must be accompanied by the - Installation Information. But this requirement does not apply if neither - you nor any third party retains the ability to install modified object - code on the User Product (for example, the work has been installed in - ROM). - - The requirement to provide Installation Information does not include a - requirement to continue to provide support service, warranty, or updates - for a work that has been modified or installed by the recipient, or for - the User Product in which it has been modified or installed. Access - to a network may be denied when the modification itself materially - and adversely affects the operation of the network or violates the - rules and protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, in - accord with this section must be in a format that is publicly documented - (and with an implementation available to the public in source code form), - and must require no special password or key for unpacking, reading or - copying. - - 7. Additional Terms. - - “Additional permissions” are terms that supplement the terms of this - License by making exceptions from one or more of its conditions. - Additional permissions that are applicable to the entire Program shall be - treated as though they were included in this License, to the extent that - they are valid under applicable law. If additional permissions apply only - to part of the Program, that part may be used separately under those - permissions, but the entire Program remains governed by this License - without regard to the additional permissions. When you convey a copy of - a covered work, you may at your option remove any additional permissions - from that copy, or from any part of it. (Additional permissions may be - written to require their own removal in certain cases when you modify the - work.) You may place additional permissions on material, added by you to - a covered work, for which you have or can give appropriate copyright - permission. - - Notwithstanding any other provision of this License, for material you add - to a covered work, you may (if authorized by the copyright holders of - that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some trade - names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that material - by anyone who conveys the material (or modified versions of it) with - contractual assumptions of liability to the recipient, for any - liability that these contractual assumptions directly impose on those - licensors and authors. - - All other non-permissive additional terms are considered “further - restrictions” within the meaning of section 10. If the Program as you - received it, or any part of it, contains a notice stating that it is - governed by this License along with a term that is a further restriction, - you may remove that term. If a license document contains a further - restriction but permits relicensing or conveying under this License, you - may add to a covered work material governed by the terms of that license - document, provided that the further restriction does not survive such - relicensing or conveying. - - If you add terms to a covered work in accord with this section, you must - place, in the relevant source files, a statement of the additional terms - that apply to those files, or a notice indicating where to find the - applicable terms. Additional terms, permissive or non-permissive, may be - stated in the form of a separately written license, or stated as - exceptions; the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly - provided under this License. Any attempt otherwise to propagate or modify - it is void, and will automatically terminate your rights under this - License (including any patent licenses granted under the third paragraph - of section 11). - - However, if you cease all violation of this License, then your license - from a particular copyright holder is reinstated (a) provisionally, - unless and until the copyright holder explicitly and finally terminates - your license, and (b) permanently, if the copyright holder fails to - notify you of the violation by some reasonable means prior to 60 days - after the cessation. - - Moreover, your license from a particular copyright holder is reinstated - permanently if the copyright holder notifies you of the violation by some - reasonable means, this is the first time you have received notice of - violation of this License (for any work) from that copyright holder, and - you cure the violation prior to 30 days after your receipt of the notice. - - Termination of your rights under this section does not terminate the - licenses of parties who have received copies or rights from you under - this License. If your rights have been terminated and not permanently - reinstated, you do not qualify to receive new licenses for the same - material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or run a - copy of the Program. Ancillary propagation of a covered work occurring - solely as a consequence of using peer-to-peer transmission to receive a - copy likewise does not require acceptance. However, nothing other than - this License grants you permission to propagate or modify any covered - work. These actions infringe copyright if you do not accept this License. - Therefore, by modifying or propagating a covered work, you indicate your - acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically receives - a license from the original licensors, to run, modify and propagate that - work, subject to this License. You are not responsible for enforcing - compliance by third parties with this License. - - An “entity transaction” is a transaction transferring control of an - organization, or substantially all assets of one, or subdividing an - organization, or merging organizations. If propagation of a covered work - results from an entity transaction, each party to that transaction who - receives a copy of the work also receives whatever licenses to the work - the party's predecessor in interest had or could give under the previous - paragraph, plus a right to possession of the Corresponding Source of the - work from the predecessor in interest, if the predecessor has it or can - get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the rights - granted or affirmed under this License. For example, you may not impose a - license fee, royalty, or other charge for exercise of rights granted - under this License, and you may not initiate litigation (including a - cross-claim or counterclaim in a lawsuit) alleging that any patent claim - is infringed by making, using, selling, offering for sale, or importing - the Program or any portion of it. - - 11. Patents. - - A “contributor” is a copyright holder who authorizes use under this - License of the Program or a work on which the Program is based. The work - thus licensed is called the contributor's “contributor version”. - - A contributor's “essential patent claims” are all patent claims owned or - controlled by the contributor, whether already acquired or hereafter - acquired, that would be infringed by some manner, permitted by this - License, of making, using, or selling its contributor version, but do not - include claims that would be infringed only as a consequence of further - modification of the contributor version. For purposes of this definition, - “control” includes the right to grant patent sublicenses in a manner - consistent with the requirements of this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free - patent license under the contributor's essential patent claims, to make, - use, sell, offer for sale, import and otherwise run, modify and propagate - the contents of its contributor version. - - In the following three paragraphs, a “patent license” is any express - agreement or commitment, however denominated, not to enforce a patent - (such as an express permission to practice a patent or covenant not to - sue for patent infringement). To “grant” such a patent license to a party - means to make such an agreement or commitment not to enforce a patent - against the party. - - If you convey a covered work, knowingly relying on a patent license, and - the Corresponding Source of the work is not available for anyone to copy, - free of charge and under the terms of this License, through a publicly - available network server or other readily accessible means, then you must - either (1) cause the Corresponding Source to be so available, or (2) - arrange to deprive yourself of the benefit of the patent license for this - particular work, or (3) arrange, in a manner consistent with the - requirements of this License, to extend the patent license to downstream - recipients. “Knowingly relying” means you have actual knowledge that, but - for the patent license, your conveying the covered work in a country, or - your recipient's use of the covered work in a country, would infringe - one or more identifiable patents in that country that you have reason - to believe are valid. - - If, pursuant to or in connection with a single transaction or - arrangement, you convey, or propagate by procuring conveyance of, a - covered work, and grant a patent license to some of the parties receiving - the covered work authorizing them to use, propagate, modify or convey a - specific copy of the covered work, then the patent license you grant is - automatically extended to all recipients of the covered work and works - based on it. - - A patent license is “discriminatory” if it does not include within the - scope of its coverage, prohibits the exercise of, or is conditioned on - the non-exercise of one or more of the rights that are specifically - granted under this License. You may not convey a covered work if you are - a party to an arrangement with a third party that is in the business of - distributing software, under which you make payment to the third party - based on the extent of your activity of conveying the work, and under - which the third party grants, to any of the parties who would receive the - covered work from you, a discriminatory patent license (a) in connection - with copies of the covered work conveyed by you (or copies made from - those copies), or (b) primarily for and in connection with specific - products or compilations that contain the covered work, unless you - entered into that arrangement, or that patent license was granted, prior - to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting any - implied license or other defenses to infringement that may otherwise be - available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot use, - propagate or convey a covered work so as to satisfy simultaneously your - obligations under this License and any other pertinent obligations, then - as a consequence you may not use, propagate or convey it at all. For - example, if you agree to terms that obligate you to collect a royalty for - further conveying from those to whom you convey the Program, the only way - you could satisfy both those terms and this License would be to refrain - entirely from conveying the Program. - - 13. Offering the Program as a Service. - - If you make the functionality of the Program or a modified version - available to third parties as a service, you must make the Service Source - Code available via network download to everyone at no charge, under the - terms of this License. Making the functionality of the Program or - modified version available to third parties as a service includes, - without limitation, enabling third parties to interact with the - functionality of the Program or modified version remotely through a - computer network, offering a service the value of which entirely or - primarily derives from the value of the Program or modified version, or - offering a service that accomplishes for users the primary purpose of the - Program or modified version. - - “Service Source Code” means the Corresponding Source for the Program or - the modified version, and the Corresponding Source for all programs that - you use to make the Program or modified version available as a service, - including, without limitation, management software, user interfaces, - application program interfaces, automation software, monitoring software, - backup software, storage software and hosting software, all such that a - user could run an instance of the service using the Service Source Code - you make available. - - 14. Revised Versions of this License. - - MongoDB, Inc. may publish revised and/or new versions of the Server Side - Public License from time to time. Such new versions will be similar in - spirit to the present version, but may differ in detail to address new - problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies that a certain numbered version of the Server Side Public - License “or any later version” applies to it, you have the option of - following the terms and conditions either of that numbered version or of - any later version published by MongoDB, Inc. If the Program does not - specify a version number of the Server Side Public License, you may - choose any version ever published by MongoDB, Inc. - - If the Program specifies that a proxy can decide which future versions of - the Server Side Public License can be used, that proxy's public statement - of acceptance of a version permanently authorizes you to choose that - version for the Program. - - Later license versions may give you additional or different permissions. - However, no additional obligations are imposed on any author or copyright - holder as a result of your choosing to follow a later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY - APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT - HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY - OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM - IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF - ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS - THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING - ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF - THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO - LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU - OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER - PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided above - cannot be given local legal effect according to their terms, reviewing - courts shall apply local law that most closely approximates an absolute - waiver of all civil liability in connection with the Program, unless a - warranty or assumption of liability accompanies a copy of the Program in - return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/MPL-2 b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/MPL-2 deleted file mode 100644 index 197b2ffd..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/MPL-2 +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/README b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/README deleted file mode 100644 index 97f1dc72..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/README +++ /dev/null @@ -1,87 +0,0 @@ -MongoDB README - -Welcome to MongoDB! - -COMPONENTS - - mongod - The database server. - mongos - Sharding router. - mongo - The database shell (uses interactive javascript). - -UTILITIES - - install_compass - Installs MongoDB Compass for your platform. - -BUILDING - - See docs/building.md. - -RUNNING - - For command line options invoke: - - $ ./mongod --help - - To run a single server database: - - $ sudo mkdir -p /data/db - $ ./mongod - $ - $ # The mongo javascript shell connects to localhost and test database by default: - $ ./mongo - > help - -INSTALLING COMPASS - - You can install compass using the install_compass script packaged with MongoDB: - - $ ./install_compass - - This will download the appropriate MongoDB Compass package for your platform - and install it. - -DRIVERS - - Client drivers for most programming languages are available at - https://docs.mongodb.com/manual/applications/drivers/. Use the shell - ("mongo") for administrative tasks. - -BUG REPORTS - - See https://github.com/mongodb/mongo/wiki/Submit-Bug-Reports. - -PACKAGING - - Packages are created dynamically by the package.py script located in the - buildscripts directory. This will generate RPM and Debian packages. - -DOCUMENTATION - - https://docs.mongodb.com/manual/ - -CLOUD HOSTED MONGODB - - https://www.mongodb.com/cloud/atlas - -FORUMS - - https://community.mongodb.com - - A forum for technical questions about using MongoDB. - - https://community.mongodb.com/c/server-dev - - A forum for technical questions about building and developing MongoDB. - -LEARN MONGODB - - https://university.mongodb.com/ - -LICENSE - - MongoDB is free and open-source. Versions released prior to October 16, - 2018 are published under the AGPL. All versions released after October - 16, 2018, including patch fixes for prior versions, are published under - the Server Side Public License (SSPL) v1. See individual files for - details. - diff --git a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES deleted file mode 100644 index 8c9e17e3..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,1568 +0,0 @@ -MongoDB uses third-party libraries or other resources that may -be distributed under licenses different than the MongoDB software. - -In the event that we accidentally failed to list a required notice, -please bring it to our attention through any of the ways detailed here : - - mongodb-dev@googlegroups.com - -The attached notices are provided for information only. - -For any licenses that require disclosure of source, sources are available at -https://github.com/mongodb/mongo. - - -1) License Notice for Boost ---------------------------- - -http://www.boost.org/LICENSE_1_0.txt - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - -3) License Notice for PCRE --------------------------- - -http://www.pcre.org/licence.txt - -PCRE LICENCE ------------- - -PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - -Release 7 of PCRE is distributed under the terms of the "BSD" licence, as -specified below. The documentation for PCRE, supplied in the "doc" -directory, is distributed under the same terms as the software itself. - -The basic library functions are written in C and are freestanding. Also -included in the distribution is a set of C++ wrapper functions. - - -THE BASIC LIBRARY FUNCTIONS ---------------------------- - -Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk - -University of Cambridge Computing Service, -Cambridge, England. - -Copyright (c) 1997-2008 University of Cambridge -All rights reserved. - - -THE C++ WRAPPER FUNCTIONS -------------------------- - -Contributed by: Google Inc. - -Copyright (c) 2007-2008, Google Inc. -All rights reserved. - - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -4) License notice for Aladdin MD5 ---------------------------------- - -Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -5) License notice for Snappy - http://code.google.com/p/snappy/ ---------------------------------- - Copyright 2005 and onwards Google Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - A light-weight compression algorithm. It is designed for speed of - compression and decompression, rather than for the utmost in space - savings. - - For getting better compression ratios when you are compressing data - with long repeated sequences or compressing data that is similar to - other data, while still compressing fast, you might look at first - using BMDiff and then compressing the output of BMDiff with - Snappy. - -6) License notice for Google Perftools (TCMalloc utility) ---------------------------------- -New BSD License - -Copyright (c) 1998-2006, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -7) License notice for Linenoise -------------------------------- - - Copyright (c) 2010, Salvatore Sanfilippo - Copyright (c) 2010, Pieter Noordhuis - - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -8) License notice for S2 Geometry Library ------------------------------------------ - Copyright 2005 Google Inc. All Rights Reserved. - - 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. - -9) License notice for MurmurHash --------------------------------- - - Copyright (c) 2010-2012 Austin Appleby - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -10) License notice for Snowball - Copyright (c) 2001, Dr Martin Porter - All rights reserved. - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -11) License notice for yaml-cpp -------------------------------- - -Copyright (c) 2008 Jesse Beder. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -12) License notice for zlib ---------------------------- - -http://www.zlib.net/zlib_license.html - -zlib.h -- interface of the 'zlib' general purpose compression library -version 1.2.8, April 28th, 2013 - -Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -13) License notice for 3rd party software included in the WiredTiger library ----------------------------------------------------------------------------- - -http://source.wiredtiger.com/license.html - -WiredTiger Distribution Files | Copyright Holder | License ------------------------------ | ----------------------------------- | ---------------------- -src/include/bitstring.i | University of California, Berkeley | BSD-3-Clause License -src/include/queue.h | University of California, Berkeley | BSD-3-Clause License -src/os_posix/os_getopt.c | University of California, Berkeley | BSD-3-Clause License -src/support/hash_city.c | Google, Inc. | The MIT License -src/support/hash_fnv.c | Authors | Public Domain - - -Other optional 3rd party software included in the WiredTiger distribution is removed by MongoDB. - - -BSD-3-CLAUSE LICENSE --------------------- - -http://www.opensource.org/licenses/BSD-3-Clause - -Copyright (c) 1987, 1989, 1991, 1993, 1994 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - - -THE MIT LICENSE ---------------- - -http://www.opensource.org/licenses/MIT - -Copyright (c) 2011 Google, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -14) License Notice for SpiderMonkey ------------------------------------ - -|------------------------------------------------|------------------|---------------| -| SpiderMonkey Distribution Files | Copyright Holder | License | -|------------------------------------------------|------------------|---------------| -| js/src/jit/shared/AssemblerBuffer-x86-shared.h | Apple, Inc | BSD-2-Clause | -| js/src/jit/shared/BaseAssembler-x86-shared.h | | | -|------------------------------------------------|------------------|---------------| -| js/src/builtin/ | Google, Inc | BSD-3-Clause | -| js/src/irregexp/ | | | -| js/src/jit/arm/ | | | -| js/src/jit/mips/ | | | -| mfbt/double-conversion/ | | | -|------------------------------------------------|------------------|---------------| -| intl/icu/source/common/unicode/ | IBM, Inc | ICU | -|------------------------------------------------|------------------|---------------| -| js/src/asmjs/ | Mozilla, Inc | Apache2 | -|------------------------------------------------|------------------|---------------| -| js/public/ | Mozilla, Inc | MPL2 | -| js/src/ | | | -| mfbt | | | -|------------------------------------------------|------------------|---------------| -| js/src/vm/Unicode.cpp | None | Public Domain | -|------------------------------------------------|------------------|---------------| -| mfbt/lz4.c | Yann Collet | BSD-2-Clause | -| mfbt/lz4.h | | | -|------------------------------------------------|------------------|---------------| - -Other optional 3rd party software included in the SpiderMonkey distribution is removed by MongoDB. - - -Apple, Inc: BSD-2-Clause ------------------------- - -Copyright (C) 2008 Apple Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Google, Inc: BSD-3-Clause -------------------------- - -Copyright 2012 the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -ICU License - ICU 1.8.1 and later ---------------------------------- - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2012 International Business Machines Corporation and -others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, provided that the above copyright notice(s) and this -permission notice appear in all copies of the Software and that both the -above copyright notice(s) and this permission notice appear in supporting -documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE -BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization of the -copyright holder. - -All trademarks and registered trademarks mentioned herein are the property -of their respective owners. - - -Mozilla, Inc: Apache 2 ----------------------- - -Copyright 2014 Mozilla Foundation - -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. - - -Mozilla, Inc: MPL 2 -------------------- - -Copyright 2014 Mozilla Foundation - -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -Public Domain -------------- - -Any copyright is dedicated to the Public Domain. -http://creativecommons.org/licenses/publicdomain/ - - -LZ4: BSD-2-Clause ------------------ - -Copyright (C) 2011-2014, Yann Collet. -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 source repository : http://code.google.com/p/lz4/ -- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c - -15) License Notice for Intel DFP Math Library ---------------------------------------------- - -Copyright (c) 2011, Intel Corp. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - his list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -16) License Notice for Unicode Data ------------------------------------ - -Copyright © 1991-2015 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -17 ) License Notice for Valgrind.h ----------------------------------- - ----------------------------------------------------------------- - -Notice that the following BSD-style license applies to this one -file (valgrind.h) only. The rest of Valgrind is licensed under the -terms of the GNU General Public License, version 2, unless -otherwise indicated. See the COPYING file in the source -distribution for details. - ----------------------------------------------------------------- - -This file is part of Valgrind, a dynamic binary instrumentation -framework. - -Copyright (C) 2000-2015 Julian Seward. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - -4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------- - -Notice that the above BSD-style license applies to this one file -(valgrind.h) only. The entire rest of Valgrind is licensed under -the terms of the GNU General Public License, version 2. See the -COPYING file in the source distribution for details. - ----------------------------------------------------------------- - -18) License notice for ICU4C ----------------------------- - -ICU License - ICU 1.8.1 and later - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2016 International Business Machines Corporation and others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY -SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER -RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - - -All trademarks and registered trademarks mentioned herein are the -property of their respective owners. - ---------------------- - -Third-Party Software Licenses - -This section contains third-party software notices and/or additional -terms for licensed third-party software components included within ICU -libraries. - -1. Unicode Data Files and Software - -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2016 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) - - # The Google Chrome software developed by Google is licensed under - # the BSD license. Other software included in this distribution is - # provided under other licenses, as set forth below. - # - # The BSD License - # http://opensource.org/licenses/bsd-license.php - # Copyright (C) 2006-2008, Google Inc. - # - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided with - # the distribution. - # Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - # - # The word list in cjdict.txt are generated by combining three word lists - # listed below with further processing for compound word breaking. The - # frequency is generated with an iterative training against Google web - # corpora. - # - # * Libtabe (Chinese) - # - https://sourceforge.net/project/?group_id=1519 - # - Its license terms and conditions are shown below. - # - # * IPADIC (Japanese) - # - http://chasen.aist-nara.ac.jp/chasen/distribution.html - # - Its license terms and conditions are shown below. - # - # ---------COPYING.libtabe ---- BEGIN-------------------- - # - # /* - # * Copyrighy (c) 1999 TaBE Project. - # * Copyright (c) 1999 Pai-Hsiang Hsiao. - # * All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the TaBE Project nor the names of its - # * contributors may be used to endorse or promote products derived - # * from this software without specific prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # /* - # * Copyright (c) 1999 Computer Systems and Communication Lab, - # * Institute of Information Science, Academia - # * Sinica. All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the Computer Systems and Communication Lab - # * nor the names of its contributors may be used to endorse or - # * promote products derived from this software without specific - # * prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, - # University of Illinois - # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 - # - # ---------------COPYING.libtabe-----END-------------------------------- - # - # - # ---------------COPYING.ipadic-----BEGIN------------------------------- - # - # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science - # and Technology. All Rights Reserved. - # - # Use, reproduction, and distribution of this software is permitted. - # Any copy of this software, whether in its original form or modified, - # must include both the above copyright notice and the following - # paragraphs. - # - # Nara Institute of Science and Technology (NAIST), - # the copyright holders, disclaims all warranties with regard to this - # software, including all implied warranties of merchantability and - # fitness, in no event shall NAIST be liable for - # any special, indirect or consequential damages or any damages - # whatsoever resulting from loss of use, data or profits, whether in an - # action of contract, negligence or other tortuous action, arising out - # of or in connection with the use or performance of this software. - # - # A large portion of the dictionary entries - # originate from ICOT Free Software. The following conditions for ICOT - # Free Software applies to the current dictionary as well. - # - # Each User may also freely distribute the Program, whether in its - # original form or modified, to any third party or parties, PROVIDED - # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear - # on, or be attached to, the Program, which is distributed substantially - # in the same form as set out herein and that such intended - # distribution, if actually made, will neither violate or otherwise - # contravene any of the laws and regulations of the countries having - # jurisdiction over the User or the intended distribution itself. - # - # NO WARRANTY - # - # The program was produced on an experimental basis in the course of the - # research and development conducted during the project and is provided - # to users as so produced on an experimental basis. Accordingly, the - # program is provided without any warranty whatsoever, whether express, - # implied, statutory or otherwise. The term "warranty" used herein - # includes, but is not limited to, any warranty of the quality, - # performance, merchantability and fitness for a particular purpose of - # the program and the nonexistence of any infringement or violation of - # any right of any third party. - # - # Each user of the program will agree and understand, and be deemed to - # have agreed and understood, that there is no warranty whatsoever for - # the program and, accordingly, the entire risk arising from or - # otherwise connected with the program is assumed by the user. - # - # Therefore, neither ICOT, the copyright holder, or any other - # organization that participated in or was otherwise related to the - # development of the program and their respective officials, directors, - # officers and other employees shall be held liable for any and all - # damages, including, without limitation, general, special, incidental - # and consequential damages, arising out of or otherwise in connection - # with the use or inability to use the program or any product, material - # or result produced or otherwise obtained by using the program, - # regardless of whether they have been advised of, or otherwise had - # knowledge of, the possibility of such damages at any time during the - # project or thereafter. Each user will be deemed to have agreed to the - # foregoing by his or her commencement of use of the program. The term - # "use" as used herein includes, but is not limited to, the use, - # modification, copying and distribution of the program and the - # production of secondary products from the program. - # - # In the case where the program, whether in its original form or - # modified, was distributed or delivered to or received by a user from - # any person, organization or entity other than ICOT, unless it makes or - # grants independently of ICOT any specific warranty to the user in - # writing, such person, organization or entity, will also be exempted - # from and not be held liable to the user for any such damages as noted - # above as far as the program is concerned. - # - # ---------------COPYING.ipadic-----END---------------------------------- - -3. Lao Word Break Dictionary Data (laodict.txt) - - # Copyright (c) 2013 International Business Machines Corporation - # and others. All Rights Reserved. - # - # Project: http://code.google.com/p/lao-dictionary/ - # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt - # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt - # (copied below) - # - # This file is derived from the above dictionary, with slight - # modifications. - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, - # are permitted provided that the following conditions are met: - # - # - # Redistributions of source code must retain the above copyright notice, this - # list of conditions and the following disclaimer. Redistributions in - # binary form must reproduce the above copyright notice, this list of - # conditions and the following disclaimer in the documentation and/or - # other materials provided with the distribution. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # OF THE POSSIBILITY OF SUCH DAMAGE. - # -------------------------------------------------------------------------- - -4. Burmese Word Break Dictionary Data (burmesedict.txt) - - # Copyright (c) 2014 International Business Machines Corporation - # and others. All Rights Reserved. - # - # This list is part of a project hosted at: - # github.com/kanyawtech/myanmar-karen-word-lists - # - # -------------------------------------------------------------------------- - # Copyright (c) 2013, LeRoy Benjamin Sharon - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: Redistributions of source code must retain the above - # copyright notice, this list of conditions and the following - # disclaimer. Redistributions in binary form must reproduce the - # above copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided - # with the distribution. - # - # Neither the name Myanmar Karen Word Lists, nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - # -------------------------------------------------------------------------- - -5. Time Zone Database - - ICU uses the public domain data and code derived from Time Zone -Database for its time zone support. The ownership of the TZ database -is explained in BCP 175: Procedure for Maintaining the Time Zone -Database section 7. - - # 7. Database Ownership - # - # The TZ database itself is not an IETF Contribution or an IETF - # document. Rather it is a pre-existing and regularly updated work - # that is in the public domain, and is intended to remain in the - # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do - # not apply to the TZ Database or contributions that individuals make - # to it. Should any claims be made and substantiated against the TZ - # Database, the organization that is providing the IANA - # Considerations defined in this RFC, under the memorandum of - # understanding with the IETF, currently ICANN, may act in accordance - # with all competent court orders. No ownership claims will be made - # by ICANN or the IETF Trust on the database or the code. Any person - # making a contribution to the database or code waives all rights to - # future claims in that contribution or in the TZ Database. - -19) License notice for timelib ------------------------------- - -The MIT License (MIT) - -Copyright (c) 2015-2017 Derick Rethans -Copyright (c) 2017 MongoDB, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -20) License notice for windows dirent implementation ----------------------------------------------------- - - * Dirent interface for Microsoft Visual Studio - * Version 1.21 - * - * Copyright (C) 2006-2012 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - - - 21) License notice for abseil-cpp ----------------------------- - - Copyright (c) Google Inc. - - 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. - - 22) License notice for Zstandard ----------------------------- - - BSD License - - For Zstandard software - - Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 23) License notice for ASIO ----------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 24) License notice for MPark.Variant -------------------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 25) License notice for fmt ---------------------------- - -Copyright (c) 2012 - present, Victor Zverovich -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 26) License notice for SafeInt ---------------------------- - -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. - -MIT License - -Copyright (c) 2018 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - 27) License Notice for Raft TLA+ Specification ------------------------------------------------ - -https://github.com/ongardie/dissertation/blob/master/LICENSE - -Copyright 2014 Diego Ongaro. - -Some of our TLA+ specifications are based on the Raft TLA+ specification by Diego Ongaro. - -End diff --git a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md deleted file mode 100644 index 550ae4ed..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2014 MongoDB, Inc. - -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/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md deleted file mode 100644 index e60e0cd0..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/README.md +++ /dev/null @@ -1,72 +0,0 @@ -MongoDB Tools -=================================== - - - **bsondump** - _display BSON files in a human-readable format_ - - **mongoimport** - _Convert data from JSON, TSV or CSV and insert them into a collection_ - - **mongoexport** - _Write an existing collection to CSV or JSON format_ - - **mongodump/mongorestore** - _Dump MongoDB backups to disk in .BSON format, or restore them to a live database_ - - **mongostat** - _Monitor live MongoDB servers, replica sets, or sharded clusters_ - - **mongofiles** - _Read, write, delete, or update files in [GridFS](http://docs.mongodb.org/manual/core/gridfs/)_ - - **mongotop** - _Monitor read/write activity on a mongo server_ - - -Report any bugs, improvements, or new feature requests at https://jira.mongodb.org/browse/TOOLS - -Building Tools ---------------- - -We currently build the tools with Go version 1.15. Other Go versions may work but they are untested. - -Using `go get` to directly build the tools will not work. To build them, it's recommended to first clone this repository: - -``` -git clone https://github.com/mongodb/mongo-tools -cd mongo-tools -``` - -Then run `./make build` to build all the tools, placing them in the `bin` directory inside the repository. - -You can also build a subset of the tools using the `-tools` option. For example, `./make build -tools=mongodump,mongorestore` builds only `mongodump` and `mongorestore`. - -To use the build/test scripts in this repository, you **_must_** set GOROOT to your Go root directory. This may depend on how you installed Go. - -``` -export GOROOT=/usr/local/go -``` - -Updating Dependencies ---------------- -Starting with version 100.3.1, the tools use `go mod` to manage dependencies. All dependencies are listed in the `go.mod` file and are directly vendored in the `vendor` directory. - -In order to make changes to dependencies, you first need to change the `go.mod` file. You can manually edit that file to add/update/remove entries, or you can run the following in the repository directory: - -``` -go mod edit -require=@ # for adding or updating a dependency -go mod edit -droprequire= # for removing a dependency -``` - -Then run `go mod vendor -v` to reconstruct the `vendor` directory to match the changed `go.mod` file. - -Optionally, run `go mod tidy -v` to ensure that the `go.mod` file matches the `mongo-tools` source code. - -Contributing ---------------- -See our [Contributor's Guide](CONTRIBUTING.md). - -Documentation ---------------- -See the MongoDB packages [documentation](https://docs.mongodb.org/database-tools/). - -For documentation on older versions of the MongoDB, reference that version of the [MongoDB Server Manual](docs.mongodb.com/manual): - -- [MongoDB 4.2 Tools](https://docs.mongodb.org/v4.2/reference/program) -- [MongoDB 4.0 Tools](https://docs.mongodb.org/v4.0/reference/program) -- [MongoDB 3.6 Tools](https://docs.mongodb.org/v3.6/reference/program) - -Adding New Platforms Support ---------------- -See our [Adding New Platform Support Guide](PLATFORMSUPPORT.md). - -Vendoring the Change into Server Repo ---------------- -See our [Vendor the Change into Server Repo](SERVERVENDORING.md). diff --git a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES b/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES deleted file mode 100644 index 3d75e64b..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-linux-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,3319 +0,0 @@ ---------------------------------------------------------------------- -License notice for hashicorp/go-rootcerts ---------------------------------------------------------------------- - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - ---------------------------------------------------------------------- -License notice for JSON and CSV code from github.com/golang/go ---------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/escaper ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Lucas Morales - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo/bson ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/openssl ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/3rf/mongo-lint ----------------------------------------------------------------------- - -Copyright (c) 2013 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/go-stack/stack ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Chris Hines - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/golang/snappy ----------------------------------------------------------------------- - -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/google/gopacket ----------------------------------------------------------------------- - -Copyright (c) 2012 Google, Inc. All rights reserved. -Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Andreas Krennmair, Google, nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/gopherjs/gopherjs ----------------------------------------------------------------------- - -Copyright (c) 2013 Richard Musiol. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/howeyc/gopass ----------------------------------------------------------------------- - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/jessevdk/go-flags ----------------------------------------------------------------------- - -Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/jtolds/gls ----------------------------------------------------------------------- - -Copyright (c) 2013, Space Monkey, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mattn/go-runewidth ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mongodb/mongo-go-driver ----------------------------------------------------------------------- - - 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. - ----------------------------------------------------------------------- -License notice for github.com/nsf/termbox-go ----------------------------------------------------------------------- - -Copyright (C) 2012 termbox-go authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/patrickmn/go-cache ----------------------------------------------------------------------- - -Copyright (c) 2012-2015 Patrick Mylund Nielsen and the go-cache contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions ----------------------------------------------------------------------- - -Copyright (c) 2015 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/go-render ----------------------------------------------------------------------- - -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglematchers ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglemock ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/ogletest ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/reqtrace ----------------------------------------------------------------------- - - 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. - - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey ----------------------------------------------------------------------- - -Copyright (c) 2014 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey/web/client/resources/fonts/Open_Sans ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/spacemonkeygo/spacelog ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/scram ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/stringprep ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/youmark/pkcs8 ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 youmark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for golang.org/x/crypto ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/sync ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/text ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for gopkg.in/tomb.v2 ----------------------------------------------------------------------- - -tomb - support for clean goroutine termination in Go. - -Copyright (c) 2010-2011 - Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt deleted file mode 100644 index b01add13..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt +++ /dev/null @@ -1,557 +0,0 @@ - Server Side Public License - VERSION 1, OCTOBER 16, 2018 - - Copyright © 2018 MongoDB, Inc. - - Everyone is permitted to copy and distribute verbatim copies of this - license document, but changing it is not allowed. - - TERMS AND CONDITIONS - - 0. Definitions. - - “This License” refers to Server Side Public License. - - “Copyright” also means copyright-like laws that apply to other kinds of - works, such as semiconductor masks. - - “The Program” refers to any copyrightable work licensed under this - License. Each licensee is addressed as “you”. “Licensees” and - “recipients” may be individuals or organizations. - - To “modify” a work means to copy from or adapt all or part of the work in - a fashion requiring copyright permission, other than the making of an - exact copy. The resulting work is called a “modified version” of the - earlier work or a work “based on” the earlier work. - - A “covered work” means either the unmodified Program or a work based on - the Program. - - To “propagate” a work means to do anything with it that, without - permission, would make you directly or secondarily liable for - infringement under applicable copyright law, except executing it on a - computer or modifying a private copy. Propagation includes copying, - distribution (with or without modification), making available to the - public, and in some countries other activities as well. - - To “convey” a work means any kind of propagation that enables other - parties to make or receive copies. Mere interaction with a user through a - computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays “Appropriate Legal Notices” to the - extent that it includes a convenient and prominently visible feature that - (1) displays an appropriate copyright notice, and (2) tells the user that - there is no warranty for the work (except to the extent that warranties - are provided), that licensees may convey the work under this License, and - how to view a copy of this License. If the interface presents a list of - user commands or options, such as a menu, a prominent item in the list - meets this criterion. - - 1. Source Code. - - The “source code” for a work means the preferred form of the work for - making modifications to it. “Object code” means any non-source form of a - work. - - A “Standard Interface” means an interface that either is an official - standard defined by a recognized standards body, or, in the case of - interfaces specified for a particular programming language, one that is - widely used among developers working in that language. The “System - Libraries” of an executable work include anything, other than the work as - a whole, that (a) is included in the normal form of packaging a Major - Component, but which is not part of that Major Component, and (b) serves - only to enable use of the work with that Major Component, or to implement - a Standard Interface for which an implementation is available to the - public in source code form. A “Major Component”, in this context, means a - major essential component (kernel, window system, and so on) of the - specific operating system (if any) on which the executable work runs, or - a compiler used to produce the work, or an object code interpreter used - to run it. - - The “Corresponding Source” for a work in object code form means all the - source code needed to generate, install, and (for an executable work) run - the object code and to modify the work, including scripts to control - those activities. However, it does not include the work's System - Libraries, or general-purpose tools or generally available free programs - which are used unmodified in performing those activities but which are - not part of the work. For example, Corresponding Source includes - interface definition files associated with source files for the work, and - the source code for shared libraries and dynamically linked subprograms - that the work is specifically designed to require, such as by intimate - data communication or control flow between those subprograms and other - parts of the work. - - The Corresponding Source need not include anything that users can - regenerate automatically from other parts of the Corresponding Source. - - The Corresponding Source for a work in source code form is that same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of - copyright on the Program, and are irrevocable provided the stated - conditions are met. This License explicitly affirms your unlimited - permission to run the unmodified Program, subject to section 13. The - output from running a covered work is covered by this License only if the - output, given its content, constitutes a covered work. This License - acknowledges your rights of fair use or other equivalent, as provided by - copyright law. Subject to section 13, you may make, run and propagate - covered works that you do not convey, without conditions so long as your - license otherwise remains in force. You may convey covered works to - others for the sole purpose of having them make modifications exclusively - for you, or provide you with facilities for running those works, provided - that you comply with the terms of this License in conveying all - material for which you do not control copyright. Those thus making or - running the covered works for you must do so exclusively on your - behalf, under your direction and control, on terms that prohibit them - from making any copies of your copyrighted material outside their - relationship with you. - - Conveying under any other circumstances is permitted solely under the - conditions stated below. Sublicensing is not allowed; section 10 makes it - unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological - measure under any applicable law fulfilling obligations under article 11 - of the WIPO copyright treaty adopted on 20 December 1996, or similar laws - prohibiting or restricting circumvention of such measures. - - When you convey a covered work, you waive any legal power to forbid - circumvention of technological measures to the extent such circumvention is - effected by exercising rights under this License with respect to the - covered work, and you disclaim any intention to limit operation or - modification of the work as a means of enforcing, against the work's users, - your or third parties' legal rights to forbid circumvention of - technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you - receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice; keep - intact all notices stating that this License and any non-permissive terms - added in accord with section 7 apply to the code; keep intact all notices - of the absence of any warranty; and give all recipients a copy of this - License along with the Program. You may charge any price or no price for - each copy that you convey, and you may offer support or warranty - protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to - produce it from the Program, in the form of source code under the terms - of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified it, - and giving a relevant date. - - b) The work must carry prominent notices stating that it is released - under this License and any conditions added under section 7. This - requirement modifies the requirement in section 4 to “keep intact all - notices”. - - c) You must license the entire work, as a whole, under this License to - anyone who comes into possession of a copy. This License will therefore - apply, along with any applicable section 7 additional terms, to the - whole of the work, and all its parts, regardless of how they are - packaged. This License gives no permission to license the work in any - other way, but it does not invalidate such permission if you have - separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your work - need not make them do so. - - A compilation of a covered work with other separate and independent - works, which are not by their nature extensions of the covered work, and - which are not combined with it such as to form a larger program, in or on - a volume of a storage or distribution medium, is called an “aggregate” if - the compilation and its resulting copyright are not used to limit the - access or legal rights of the compilation's users beyond what the - individual works permit. Inclusion of a covered work in an aggregate does - not cause this License to apply to the other parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms of - sections 4 and 5, provided that you also convey the machine-readable - Corresponding Source under the terms of this License, in one of these - ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium customarily - used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a written - offer, valid for at least three years and valid for as long as you - offer spare parts or customer support for that product model, to give - anyone who possesses the object code either (1) a copy of the - Corresponding Source for all the software in the product that is - covered by this License, on a durable physical medium customarily used - for software interchange, for a price no more than your reasonable cost - of physically performing this conveying of source, or (2) access to - copy the Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This alternative is - allowed only occasionally and noncommercially, and only if you received - the object code with such an offer, in accord with subsection 6b. - - d) Convey the object code by offering access from a designated place - (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to copy - the object code is a network server, the Corresponding Source may be on - a different server (operated by you or a third party) that supports - equivalent copying facilities, provided you maintain clear directions - next to the object code saying where to find the Corresponding Source. - Regardless of what server hosts the Corresponding Source, you remain - obligated to ensure that it is available for as long as needed to - satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided you - inform other peers where the object code and Corresponding Source of - the work are being offered to the general public at no charge under - subsection 6d. - - A separable portion of the object code, whose source code is excluded - from the Corresponding Source as a System Library, need not be included - in conveying the object code work. - - A “User Product” is either (1) a “consumer product”, which means any - tangible personal property which is normally used for personal, family, - or household purposes, or (2) anything designed or sold for incorporation - into a dwelling. In determining whether a product is a consumer product, - doubtful cases shall be resolved in favor of coverage. For a particular - product received by a particular user, “normally used” refers to a - typical or common use of that class of product, regardless of the status - of the particular user or of the way in which the particular user - actually uses, or expects or is expected to use, the product. A product - is a consumer product regardless of whether the product has substantial - commercial, industrial or non-consumer uses, unless such uses represent - the only significant mode of use of the product. - - “Installation Information” for a User Product means any methods, - procedures, authorization keys, or other information required to install - and execute modified versions of a covered work in that User Product from - a modified version of its Corresponding Source. The information must - suffice to ensure that the continued functioning of the modified object - code is in no case prevented or interfered with solely because - modification has been made. - - If you convey an object code work under this section in, or with, or - specifically for use in, a User Product, and the conveying occurs as part - of a transaction in which the right of possession and use of the User - Product is transferred to the recipient in perpetuity or for a fixed term - (regardless of how the transaction is characterized), the Corresponding - Source conveyed under this section must be accompanied by the - Installation Information. But this requirement does not apply if neither - you nor any third party retains the ability to install modified object - code on the User Product (for example, the work has been installed in - ROM). - - The requirement to provide Installation Information does not include a - requirement to continue to provide support service, warranty, or updates - for a work that has been modified or installed by the recipient, or for - the User Product in which it has been modified or installed. Access - to a network may be denied when the modification itself materially - and adversely affects the operation of the network or violates the - rules and protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, in - accord with this section must be in a format that is publicly documented - (and with an implementation available to the public in source code form), - and must require no special password or key for unpacking, reading or - copying. - - 7. Additional Terms. - - “Additional permissions” are terms that supplement the terms of this - License by making exceptions from one or more of its conditions. - Additional permissions that are applicable to the entire Program shall be - treated as though they were included in this License, to the extent that - they are valid under applicable law. If additional permissions apply only - to part of the Program, that part may be used separately under those - permissions, but the entire Program remains governed by this License - without regard to the additional permissions. When you convey a copy of - a covered work, you may at your option remove any additional permissions - from that copy, or from any part of it. (Additional permissions may be - written to require their own removal in certain cases when you modify the - work.) You may place additional permissions on material, added by you to - a covered work, for which you have or can give appropriate copyright - permission. - - Notwithstanding any other provision of this License, for material you add - to a covered work, you may (if authorized by the copyright holders of - that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some trade - names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that material - by anyone who conveys the material (or modified versions of it) with - contractual assumptions of liability to the recipient, for any - liability that these contractual assumptions directly impose on those - licensors and authors. - - All other non-permissive additional terms are considered “further - restrictions” within the meaning of section 10. If the Program as you - received it, or any part of it, contains a notice stating that it is - governed by this License along with a term that is a further restriction, - you may remove that term. If a license document contains a further - restriction but permits relicensing or conveying under this License, you - may add to a covered work material governed by the terms of that license - document, provided that the further restriction does not survive such - relicensing or conveying. - - If you add terms to a covered work in accord with this section, you must - place, in the relevant source files, a statement of the additional terms - that apply to those files, or a notice indicating where to find the - applicable terms. Additional terms, permissive or non-permissive, may be - stated in the form of a separately written license, or stated as - exceptions; the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly - provided under this License. Any attempt otherwise to propagate or modify - it is void, and will automatically terminate your rights under this - License (including any patent licenses granted under the third paragraph - of section 11). - - However, if you cease all violation of this License, then your license - from a particular copyright holder is reinstated (a) provisionally, - unless and until the copyright holder explicitly and finally terminates - your license, and (b) permanently, if the copyright holder fails to - notify you of the violation by some reasonable means prior to 60 days - after the cessation. - - Moreover, your license from a particular copyright holder is reinstated - permanently if the copyright holder notifies you of the violation by some - reasonable means, this is the first time you have received notice of - violation of this License (for any work) from that copyright holder, and - you cure the violation prior to 30 days after your receipt of the notice. - - Termination of your rights under this section does not terminate the - licenses of parties who have received copies or rights from you under - this License. If your rights have been terminated and not permanently - reinstated, you do not qualify to receive new licenses for the same - material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or run a - copy of the Program. Ancillary propagation of a covered work occurring - solely as a consequence of using peer-to-peer transmission to receive a - copy likewise does not require acceptance. However, nothing other than - this License grants you permission to propagate or modify any covered - work. These actions infringe copyright if you do not accept this License. - Therefore, by modifying or propagating a covered work, you indicate your - acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically receives - a license from the original licensors, to run, modify and propagate that - work, subject to this License. You are not responsible for enforcing - compliance by third parties with this License. - - An “entity transaction” is a transaction transferring control of an - organization, or substantially all assets of one, or subdividing an - organization, or merging organizations. If propagation of a covered work - results from an entity transaction, each party to that transaction who - receives a copy of the work also receives whatever licenses to the work - the party's predecessor in interest had or could give under the previous - paragraph, plus a right to possession of the Corresponding Source of the - work from the predecessor in interest, if the predecessor has it or can - get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the rights - granted or affirmed under this License. For example, you may not impose a - license fee, royalty, or other charge for exercise of rights granted - under this License, and you may not initiate litigation (including a - cross-claim or counterclaim in a lawsuit) alleging that any patent claim - is infringed by making, using, selling, offering for sale, or importing - the Program or any portion of it. - - 11. Patents. - - A “contributor” is a copyright holder who authorizes use under this - License of the Program or a work on which the Program is based. The work - thus licensed is called the contributor's “contributor version”. - - A contributor's “essential patent claims” are all patent claims owned or - controlled by the contributor, whether already acquired or hereafter - acquired, that would be infringed by some manner, permitted by this - License, of making, using, or selling its contributor version, but do not - include claims that would be infringed only as a consequence of further - modification of the contributor version. For purposes of this definition, - “control” includes the right to grant patent sublicenses in a manner - consistent with the requirements of this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free - patent license under the contributor's essential patent claims, to make, - use, sell, offer for sale, import and otherwise run, modify and propagate - the contents of its contributor version. - - In the following three paragraphs, a “patent license” is any express - agreement or commitment, however denominated, not to enforce a patent - (such as an express permission to practice a patent or covenant not to - sue for patent infringement). To “grant” such a patent license to a party - means to make such an agreement or commitment not to enforce a patent - against the party. - - If you convey a covered work, knowingly relying on a patent license, and - the Corresponding Source of the work is not available for anyone to copy, - free of charge and under the terms of this License, through a publicly - available network server or other readily accessible means, then you must - either (1) cause the Corresponding Source to be so available, or (2) - arrange to deprive yourself of the benefit of the patent license for this - particular work, or (3) arrange, in a manner consistent with the - requirements of this License, to extend the patent license to downstream - recipients. “Knowingly relying” means you have actual knowledge that, but - for the patent license, your conveying the covered work in a country, or - your recipient's use of the covered work in a country, would infringe - one or more identifiable patents in that country that you have reason - to believe are valid. - - If, pursuant to or in connection with a single transaction or - arrangement, you convey, or propagate by procuring conveyance of, a - covered work, and grant a patent license to some of the parties receiving - the covered work authorizing them to use, propagate, modify or convey a - specific copy of the covered work, then the patent license you grant is - automatically extended to all recipients of the covered work and works - based on it. - - A patent license is “discriminatory” if it does not include within the - scope of its coverage, prohibits the exercise of, or is conditioned on - the non-exercise of one or more of the rights that are specifically - granted under this License. You may not convey a covered work if you are - a party to an arrangement with a third party that is in the business of - distributing software, under which you make payment to the third party - based on the extent of your activity of conveying the work, and under - which the third party grants, to any of the parties who would receive the - covered work from you, a discriminatory patent license (a) in connection - with copies of the covered work conveyed by you (or copies made from - those copies), or (b) primarily for and in connection with specific - products or compilations that contain the covered work, unless you - entered into that arrangement, or that patent license was granted, prior - to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting any - implied license or other defenses to infringement that may otherwise be - available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot use, - propagate or convey a covered work so as to satisfy simultaneously your - obligations under this License and any other pertinent obligations, then - as a consequence you may not use, propagate or convey it at all. For - example, if you agree to terms that obligate you to collect a royalty for - further conveying from those to whom you convey the Program, the only way - you could satisfy both those terms and this License would be to refrain - entirely from conveying the Program. - - 13. Offering the Program as a Service. - - If you make the functionality of the Program or a modified version - available to third parties as a service, you must make the Service Source - Code available via network download to everyone at no charge, under the - terms of this License. Making the functionality of the Program or - modified version available to third parties as a service includes, - without limitation, enabling third parties to interact with the - functionality of the Program or modified version remotely through a - computer network, offering a service the value of which entirely or - primarily derives from the value of the Program or modified version, or - offering a service that accomplishes for users the primary purpose of the - Program or modified version. - - “Service Source Code” means the Corresponding Source for the Program or - the modified version, and the Corresponding Source for all programs that - you use to make the Program or modified version available as a service, - including, without limitation, management software, user interfaces, - application program interfaces, automation software, monitoring software, - backup software, storage software and hosting software, all such that a - user could run an instance of the service using the Service Source Code - you make available. - - 14. Revised Versions of this License. - - MongoDB, Inc. may publish revised and/or new versions of the Server Side - Public License from time to time. Such new versions will be similar in - spirit to the present version, but may differ in detail to address new - problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies that a certain numbered version of the Server Side Public - License “or any later version” applies to it, you have the option of - following the terms and conditions either of that numbered version or of - any later version published by MongoDB, Inc. If the Program does not - specify a version number of the Server Side Public License, you may - choose any version ever published by MongoDB, Inc. - - If the Program specifies that a proxy can decide which future versions of - the Server Side Public License can be used, that proxy's public statement - of acceptance of a version permanently authorizes you to choose that - version for the Program. - - Later license versions may give you additional or different permissions. - However, no additional obligations are imposed on any author or copyright - holder as a result of your choosing to follow a later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY - APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT - HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY - OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM - IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF - ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS - THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING - ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF - THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO - LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU - OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER - PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided above - cannot be given local legal effect according to their terms, reviewing - courts shall apply local law that most closely approximates an absolute - waiver of all civil liability in connection with the Program, unless a - warranty or assumption of liability accompanies a copy of the Program in - return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 deleted file mode 100644 index 197b2ffd..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/MPL-2 +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README deleted file mode 100644 index 97f1dc72..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/README +++ /dev/null @@ -1,87 +0,0 @@ -MongoDB README - -Welcome to MongoDB! - -COMPONENTS - - mongod - The database server. - mongos - Sharding router. - mongo - The database shell (uses interactive javascript). - -UTILITIES - - install_compass - Installs MongoDB Compass for your platform. - -BUILDING - - See docs/building.md. - -RUNNING - - For command line options invoke: - - $ ./mongod --help - - To run a single server database: - - $ sudo mkdir -p /data/db - $ ./mongod - $ - $ # The mongo javascript shell connects to localhost and test database by default: - $ ./mongo - > help - -INSTALLING COMPASS - - You can install compass using the install_compass script packaged with MongoDB: - - $ ./install_compass - - This will download the appropriate MongoDB Compass package for your platform - and install it. - -DRIVERS - - Client drivers for most programming languages are available at - https://docs.mongodb.com/manual/applications/drivers/. Use the shell - ("mongo") for administrative tasks. - -BUG REPORTS - - See https://github.com/mongodb/mongo/wiki/Submit-Bug-Reports. - -PACKAGING - - Packages are created dynamically by the package.py script located in the - buildscripts directory. This will generate RPM and Debian packages. - -DOCUMENTATION - - https://docs.mongodb.com/manual/ - -CLOUD HOSTED MONGODB - - https://www.mongodb.com/cloud/atlas - -FORUMS - - https://community.mongodb.com - - A forum for technical questions about using MongoDB. - - https://community.mongodb.com/c/server-dev - - A forum for technical questions about building and developing MongoDB. - -LEARN MONGODB - - https://university.mongodb.com/ - -LICENSE - - MongoDB is free and open-source. Versions released prior to October 16, - 2018 are published under the AGPL. All versions released after October - 16, 2018, including patch fixes for prior versions, are published under - the Server Side Public License (SSPL) v1. See individual files for - details. - diff --git a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES deleted file mode 100644 index 8c9e17e3..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,1568 +0,0 @@ -MongoDB uses third-party libraries or other resources that may -be distributed under licenses different than the MongoDB software. - -In the event that we accidentally failed to list a required notice, -please bring it to our attention through any of the ways detailed here : - - mongodb-dev@googlegroups.com - -The attached notices are provided for information only. - -For any licenses that require disclosure of source, sources are available at -https://github.com/mongodb/mongo. - - -1) License Notice for Boost ---------------------------- - -http://www.boost.org/LICENSE_1_0.txt - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - -3) License Notice for PCRE --------------------------- - -http://www.pcre.org/licence.txt - -PCRE LICENCE ------------- - -PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - -Release 7 of PCRE is distributed under the terms of the "BSD" licence, as -specified below. The documentation for PCRE, supplied in the "doc" -directory, is distributed under the same terms as the software itself. - -The basic library functions are written in C and are freestanding. Also -included in the distribution is a set of C++ wrapper functions. - - -THE BASIC LIBRARY FUNCTIONS ---------------------------- - -Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk - -University of Cambridge Computing Service, -Cambridge, England. - -Copyright (c) 1997-2008 University of Cambridge -All rights reserved. - - -THE C++ WRAPPER FUNCTIONS -------------------------- - -Contributed by: Google Inc. - -Copyright (c) 2007-2008, Google Inc. -All rights reserved. - - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -4) License notice for Aladdin MD5 ---------------------------------- - -Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -5) License notice for Snappy - http://code.google.com/p/snappy/ ---------------------------------- - Copyright 2005 and onwards Google Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - A light-weight compression algorithm. It is designed for speed of - compression and decompression, rather than for the utmost in space - savings. - - For getting better compression ratios when you are compressing data - with long repeated sequences or compressing data that is similar to - other data, while still compressing fast, you might look at first - using BMDiff and then compressing the output of BMDiff with - Snappy. - -6) License notice for Google Perftools (TCMalloc utility) ---------------------------------- -New BSD License - -Copyright (c) 1998-2006, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -7) License notice for Linenoise -------------------------------- - - Copyright (c) 2010, Salvatore Sanfilippo - Copyright (c) 2010, Pieter Noordhuis - - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -8) License notice for S2 Geometry Library ------------------------------------------ - Copyright 2005 Google Inc. All Rights Reserved. - - 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. - -9) License notice for MurmurHash --------------------------------- - - Copyright (c) 2010-2012 Austin Appleby - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -10) License notice for Snowball - Copyright (c) 2001, Dr Martin Porter - All rights reserved. - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -11) License notice for yaml-cpp -------------------------------- - -Copyright (c) 2008 Jesse Beder. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -12) License notice for zlib ---------------------------- - -http://www.zlib.net/zlib_license.html - -zlib.h -- interface of the 'zlib' general purpose compression library -version 1.2.8, April 28th, 2013 - -Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -13) License notice for 3rd party software included in the WiredTiger library ----------------------------------------------------------------------------- - -http://source.wiredtiger.com/license.html - -WiredTiger Distribution Files | Copyright Holder | License ------------------------------ | ----------------------------------- | ---------------------- -src/include/bitstring.i | University of California, Berkeley | BSD-3-Clause License -src/include/queue.h | University of California, Berkeley | BSD-3-Clause License -src/os_posix/os_getopt.c | University of California, Berkeley | BSD-3-Clause License -src/support/hash_city.c | Google, Inc. | The MIT License -src/support/hash_fnv.c | Authors | Public Domain - - -Other optional 3rd party software included in the WiredTiger distribution is removed by MongoDB. - - -BSD-3-CLAUSE LICENSE --------------------- - -http://www.opensource.org/licenses/BSD-3-Clause - -Copyright (c) 1987, 1989, 1991, 1993, 1994 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - - -THE MIT LICENSE ---------------- - -http://www.opensource.org/licenses/MIT - -Copyright (c) 2011 Google, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -14) License Notice for SpiderMonkey ------------------------------------ - -|------------------------------------------------|------------------|---------------| -| SpiderMonkey Distribution Files | Copyright Holder | License | -|------------------------------------------------|------------------|---------------| -| js/src/jit/shared/AssemblerBuffer-x86-shared.h | Apple, Inc | BSD-2-Clause | -| js/src/jit/shared/BaseAssembler-x86-shared.h | | | -|------------------------------------------------|------------------|---------------| -| js/src/builtin/ | Google, Inc | BSD-3-Clause | -| js/src/irregexp/ | | | -| js/src/jit/arm/ | | | -| js/src/jit/mips/ | | | -| mfbt/double-conversion/ | | | -|------------------------------------------------|------------------|---------------| -| intl/icu/source/common/unicode/ | IBM, Inc | ICU | -|------------------------------------------------|------------------|---------------| -| js/src/asmjs/ | Mozilla, Inc | Apache2 | -|------------------------------------------------|------------------|---------------| -| js/public/ | Mozilla, Inc | MPL2 | -| js/src/ | | | -| mfbt | | | -|------------------------------------------------|------------------|---------------| -| js/src/vm/Unicode.cpp | None | Public Domain | -|------------------------------------------------|------------------|---------------| -| mfbt/lz4.c | Yann Collet | BSD-2-Clause | -| mfbt/lz4.h | | | -|------------------------------------------------|------------------|---------------| - -Other optional 3rd party software included in the SpiderMonkey distribution is removed by MongoDB. - - -Apple, Inc: BSD-2-Clause ------------------------- - -Copyright (C) 2008 Apple Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Google, Inc: BSD-3-Clause -------------------------- - -Copyright 2012 the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -ICU License - ICU 1.8.1 and later ---------------------------------- - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2012 International Business Machines Corporation and -others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, provided that the above copyright notice(s) and this -permission notice appear in all copies of the Software and that both the -above copyright notice(s) and this permission notice appear in supporting -documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE -BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization of the -copyright holder. - -All trademarks and registered trademarks mentioned herein are the property -of their respective owners. - - -Mozilla, Inc: Apache 2 ----------------------- - -Copyright 2014 Mozilla Foundation - -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. - - -Mozilla, Inc: MPL 2 -------------------- - -Copyright 2014 Mozilla Foundation - -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -Public Domain -------------- - -Any copyright is dedicated to the Public Domain. -http://creativecommons.org/licenses/publicdomain/ - - -LZ4: BSD-2-Clause ------------------ - -Copyright (C) 2011-2014, Yann Collet. -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 source repository : http://code.google.com/p/lz4/ -- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c - -15) License Notice for Intel DFP Math Library ---------------------------------------------- - -Copyright (c) 2011, Intel Corp. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - his list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -16) License Notice for Unicode Data ------------------------------------ - -Copyright © 1991-2015 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -17 ) License Notice for Valgrind.h ----------------------------------- - ----------------------------------------------------------------- - -Notice that the following BSD-style license applies to this one -file (valgrind.h) only. The rest of Valgrind is licensed under the -terms of the GNU General Public License, version 2, unless -otherwise indicated. See the COPYING file in the source -distribution for details. - ----------------------------------------------------------------- - -This file is part of Valgrind, a dynamic binary instrumentation -framework. - -Copyright (C) 2000-2015 Julian Seward. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - -4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------- - -Notice that the above BSD-style license applies to this one file -(valgrind.h) only. The entire rest of Valgrind is licensed under -the terms of the GNU General Public License, version 2. See the -COPYING file in the source distribution for details. - ----------------------------------------------------------------- - -18) License notice for ICU4C ----------------------------- - -ICU License - ICU 1.8.1 and later - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2016 International Business Machines Corporation and others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY -SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER -RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - - -All trademarks and registered trademarks mentioned herein are the -property of their respective owners. - ---------------------- - -Third-Party Software Licenses - -This section contains third-party software notices and/or additional -terms for licensed third-party software components included within ICU -libraries. - -1. Unicode Data Files and Software - -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2016 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) - - # The Google Chrome software developed by Google is licensed under - # the BSD license. Other software included in this distribution is - # provided under other licenses, as set forth below. - # - # The BSD License - # http://opensource.org/licenses/bsd-license.php - # Copyright (C) 2006-2008, Google Inc. - # - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided with - # the distribution. - # Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - # - # The word list in cjdict.txt are generated by combining three word lists - # listed below with further processing for compound word breaking. The - # frequency is generated with an iterative training against Google web - # corpora. - # - # * Libtabe (Chinese) - # - https://sourceforge.net/project/?group_id=1519 - # - Its license terms and conditions are shown below. - # - # * IPADIC (Japanese) - # - http://chasen.aist-nara.ac.jp/chasen/distribution.html - # - Its license terms and conditions are shown below. - # - # ---------COPYING.libtabe ---- BEGIN-------------------- - # - # /* - # * Copyrighy (c) 1999 TaBE Project. - # * Copyright (c) 1999 Pai-Hsiang Hsiao. - # * All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the TaBE Project nor the names of its - # * contributors may be used to endorse or promote products derived - # * from this software without specific prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # /* - # * Copyright (c) 1999 Computer Systems and Communication Lab, - # * Institute of Information Science, Academia - # * Sinica. All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the Computer Systems and Communication Lab - # * nor the names of its contributors may be used to endorse or - # * promote products derived from this software without specific - # * prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, - # University of Illinois - # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 - # - # ---------------COPYING.libtabe-----END-------------------------------- - # - # - # ---------------COPYING.ipadic-----BEGIN------------------------------- - # - # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science - # and Technology. All Rights Reserved. - # - # Use, reproduction, and distribution of this software is permitted. - # Any copy of this software, whether in its original form or modified, - # must include both the above copyright notice and the following - # paragraphs. - # - # Nara Institute of Science and Technology (NAIST), - # the copyright holders, disclaims all warranties with regard to this - # software, including all implied warranties of merchantability and - # fitness, in no event shall NAIST be liable for - # any special, indirect or consequential damages or any damages - # whatsoever resulting from loss of use, data or profits, whether in an - # action of contract, negligence or other tortuous action, arising out - # of or in connection with the use or performance of this software. - # - # A large portion of the dictionary entries - # originate from ICOT Free Software. The following conditions for ICOT - # Free Software applies to the current dictionary as well. - # - # Each User may also freely distribute the Program, whether in its - # original form or modified, to any third party or parties, PROVIDED - # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear - # on, or be attached to, the Program, which is distributed substantially - # in the same form as set out herein and that such intended - # distribution, if actually made, will neither violate or otherwise - # contravene any of the laws and regulations of the countries having - # jurisdiction over the User or the intended distribution itself. - # - # NO WARRANTY - # - # The program was produced on an experimental basis in the course of the - # research and development conducted during the project and is provided - # to users as so produced on an experimental basis. Accordingly, the - # program is provided without any warranty whatsoever, whether express, - # implied, statutory or otherwise. The term "warranty" used herein - # includes, but is not limited to, any warranty of the quality, - # performance, merchantability and fitness for a particular purpose of - # the program and the nonexistence of any infringement or violation of - # any right of any third party. - # - # Each user of the program will agree and understand, and be deemed to - # have agreed and understood, that there is no warranty whatsoever for - # the program and, accordingly, the entire risk arising from or - # otherwise connected with the program is assumed by the user. - # - # Therefore, neither ICOT, the copyright holder, or any other - # organization that participated in or was otherwise related to the - # development of the program and their respective officials, directors, - # officers and other employees shall be held liable for any and all - # damages, including, without limitation, general, special, incidental - # and consequential damages, arising out of or otherwise in connection - # with the use or inability to use the program or any product, material - # or result produced or otherwise obtained by using the program, - # regardless of whether they have been advised of, or otherwise had - # knowledge of, the possibility of such damages at any time during the - # project or thereafter. Each user will be deemed to have agreed to the - # foregoing by his or her commencement of use of the program. The term - # "use" as used herein includes, but is not limited to, the use, - # modification, copying and distribution of the program and the - # production of secondary products from the program. - # - # In the case where the program, whether in its original form or - # modified, was distributed or delivered to or received by a user from - # any person, organization or entity other than ICOT, unless it makes or - # grants independently of ICOT any specific warranty to the user in - # writing, such person, organization or entity, will also be exempted - # from and not be held liable to the user for any such damages as noted - # above as far as the program is concerned. - # - # ---------------COPYING.ipadic-----END---------------------------------- - -3. Lao Word Break Dictionary Data (laodict.txt) - - # Copyright (c) 2013 International Business Machines Corporation - # and others. All Rights Reserved. - # - # Project: http://code.google.com/p/lao-dictionary/ - # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt - # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt - # (copied below) - # - # This file is derived from the above dictionary, with slight - # modifications. - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, - # are permitted provided that the following conditions are met: - # - # - # Redistributions of source code must retain the above copyright notice, this - # list of conditions and the following disclaimer. Redistributions in - # binary form must reproduce the above copyright notice, this list of - # conditions and the following disclaimer in the documentation and/or - # other materials provided with the distribution. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # OF THE POSSIBILITY OF SUCH DAMAGE. - # -------------------------------------------------------------------------- - -4. Burmese Word Break Dictionary Data (burmesedict.txt) - - # Copyright (c) 2014 International Business Machines Corporation - # and others. All Rights Reserved. - # - # This list is part of a project hosted at: - # github.com/kanyawtech/myanmar-karen-word-lists - # - # -------------------------------------------------------------------------- - # Copyright (c) 2013, LeRoy Benjamin Sharon - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: Redistributions of source code must retain the above - # copyright notice, this list of conditions and the following - # disclaimer. Redistributions in binary form must reproduce the - # above copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided - # with the distribution. - # - # Neither the name Myanmar Karen Word Lists, nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - # -------------------------------------------------------------------------- - -5. Time Zone Database - - ICU uses the public domain data and code derived from Time Zone -Database for its time zone support. The ownership of the TZ database -is explained in BCP 175: Procedure for Maintaining the Time Zone -Database section 7. - - # 7. Database Ownership - # - # The TZ database itself is not an IETF Contribution or an IETF - # document. Rather it is a pre-existing and regularly updated work - # that is in the public domain, and is intended to remain in the - # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do - # not apply to the TZ Database or contributions that individuals make - # to it. Should any claims be made and substantiated against the TZ - # Database, the organization that is providing the IANA - # Considerations defined in this RFC, under the memorandum of - # understanding with the IETF, currently ICANN, may act in accordance - # with all competent court orders. No ownership claims will be made - # by ICANN or the IETF Trust on the database or the code. Any person - # making a contribution to the database or code waives all rights to - # future claims in that contribution or in the TZ Database. - -19) License notice for timelib ------------------------------- - -The MIT License (MIT) - -Copyright (c) 2015-2017 Derick Rethans -Copyright (c) 2017 MongoDB, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -20) License notice for windows dirent implementation ----------------------------------------------------- - - * Dirent interface for Microsoft Visual Studio - * Version 1.21 - * - * Copyright (C) 2006-2012 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - - - 21) License notice for abseil-cpp ----------------------------- - - Copyright (c) Google Inc. - - 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. - - 22) License notice for Zstandard ----------------------------- - - BSD License - - For Zstandard software - - Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 23) License notice for ASIO ----------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 24) License notice for MPark.Variant -------------------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 25) License notice for fmt ---------------------------- - -Copyright (c) 2012 - present, Victor Zverovich -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 26) License notice for SafeInt ---------------------------- - -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. - -MIT License - -Copyright (c) 2018 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - 27) License Notice for Raft TLA+ Specification ------------------------------------------------ - -https://github.com/ongardie/dissertation/blob/master/LICENSE - -Copyright 2014 Diego Ongaro. - -Some of our TLA+ specifications are based on the Raft TLA+ specification by Diego Ongaro. - -End diff --git a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md deleted file mode 100644 index 550ae4ed..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2014 MongoDB, Inc. - -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/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md deleted file mode 100644 index e60e0cd0..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/README.md +++ /dev/null @@ -1,72 +0,0 @@ -MongoDB Tools -=================================== - - - **bsondump** - _display BSON files in a human-readable format_ - - **mongoimport** - _Convert data from JSON, TSV or CSV and insert them into a collection_ - - **mongoexport** - _Write an existing collection to CSV or JSON format_ - - **mongodump/mongorestore** - _Dump MongoDB backups to disk in .BSON format, or restore them to a live database_ - - **mongostat** - _Monitor live MongoDB servers, replica sets, or sharded clusters_ - - **mongofiles** - _Read, write, delete, or update files in [GridFS](http://docs.mongodb.org/manual/core/gridfs/)_ - - **mongotop** - _Monitor read/write activity on a mongo server_ - - -Report any bugs, improvements, or new feature requests at https://jira.mongodb.org/browse/TOOLS - -Building Tools ---------------- - -We currently build the tools with Go version 1.15. Other Go versions may work but they are untested. - -Using `go get` to directly build the tools will not work. To build them, it's recommended to first clone this repository: - -``` -git clone https://github.com/mongodb/mongo-tools -cd mongo-tools -``` - -Then run `./make build` to build all the tools, placing them in the `bin` directory inside the repository. - -You can also build a subset of the tools using the `-tools` option. For example, `./make build -tools=mongodump,mongorestore` builds only `mongodump` and `mongorestore`. - -To use the build/test scripts in this repository, you **_must_** set GOROOT to your Go root directory. This may depend on how you installed Go. - -``` -export GOROOT=/usr/local/go -``` - -Updating Dependencies ---------------- -Starting with version 100.3.1, the tools use `go mod` to manage dependencies. All dependencies are listed in the `go.mod` file and are directly vendored in the `vendor` directory. - -In order to make changes to dependencies, you first need to change the `go.mod` file. You can manually edit that file to add/update/remove entries, or you can run the following in the repository directory: - -``` -go mod edit -require=@ # for adding or updating a dependency -go mod edit -droprequire= # for removing a dependency -``` - -Then run `go mod vendor -v` to reconstruct the `vendor` directory to match the changed `go.mod` file. - -Optionally, run `go mod tidy -v` to ensure that the `go.mod` file matches the `mongo-tools` source code. - -Contributing ---------------- -See our [Contributor's Guide](CONTRIBUTING.md). - -Documentation ---------------- -See the MongoDB packages [documentation](https://docs.mongodb.org/database-tools/). - -For documentation on older versions of the MongoDB, reference that version of the [MongoDB Server Manual](docs.mongodb.com/manual): - -- [MongoDB 4.2 Tools](https://docs.mongodb.org/v4.2/reference/program) -- [MongoDB 4.0 Tools](https://docs.mongodb.org/v4.0/reference/program) -- [MongoDB 3.6 Tools](https://docs.mongodb.org/v3.6/reference/program) - -Adding New Platforms Support ---------------- -See our [Adding New Platform Support Guide](PLATFORMSUPPORT.md). - -Vendoring the Change into Server Repo ---------------- -See our [Vendor the Change into Server Repo](SERVERVENDORING.md). diff --git a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES b/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES deleted file mode 100644 index 3d75e64b..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-macos-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,3319 +0,0 @@ ---------------------------------------------------------------------- -License notice for hashicorp/go-rootcerts ---------------------------------------------------------------------- - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - ---------------------------------------------------------------------- -License notice for JSON and CSV code from github.com/golang/go ---------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/escaper ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Lucas Morales - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo/bson ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/openssl ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/3rf/mongo-lint ----------------------------------------------------------------------- - -Copyright (c) 2013 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/go-stack/stack ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Chris Hines - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/golang/snappy ----------------------------------------------------------------------- - -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/google/gopacket ----------------------------------------------------------------------- - -Copyright (c) 2012 Google, Inc. All rights reserved. -Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Andreas Krennmair, Google, nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/gopherjs/gopherjs ----------------------------------------------------------------------- - -Copyright (c) 2013 Richard Musiol. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/howeyc/gopass ----------------------------------------------------------------------- - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/jessevdk/go-flags ----------------------------------------------------------------------- - -Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/jtolds/gls ----------------------------------------------------------------------- - -Copyright (c) 2013, Space Monkey, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mattn/go-runewidth ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mongodb/mongo-go-driver ----------------------------------------------------------------------- - - 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. - ----------------------------------------------------------------------- -License notice for github.com/nsf/termbox-go ----------------------------------------------------------------------- - -Copyright (C) 2012 termbox-go authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/patrickmn/go-cache ----------------------------------------------------------------------- - -Copyright (c) 2012-2015 Patrick Mylund Nielsen and the go-cache contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions ----------------------------------------------------------------------- - -Copyright (c) 2015 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/go-render ----------------------------------------------------------------------- - -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglematchers ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglemock ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/ogletest ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/reqtrace ----------------------------------------------------------------------- - - 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. - - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey ----------------------------------------------------------------------- - -Copyright (c) 2014 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey/web/client/resources/fonts/Open_Sans ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/spacemonkeygo/spacelog ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/scram ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/stringprep ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/youmark/pkcs8 ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 youmark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for golang.org/x/crypto ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/sync ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/text ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for gopkg.in/tomb.v2 ----------------------------------------------------------------------- - -tomb - support for clean goroutine termination in Go. - -Copyright (c) 2010-2011 - Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt deleted file mode 100644 index b01add13..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/LICENSE-Community.txt +++ /dev/null @@ -1,557 +0,0 @@ - Server Side Public License - VERSION 1, OCTOBER 16, 2018 - - Copyright © 2018 MongoDB, Inc. - - Everyone is permitted to copy and distribute verbatim copies of this - license document, but changing it is not allowed. - - TERMS AND CONDITIONS - - 0. Definitions. - - “This License” refers to Server Side Public License. - - “Copyright” also means copyright-like laws that apply to other kinds of - works, such as semiconductor masks. - - “The Program” refers to any copyrightable work licensed under this - License. Each licensee is addressed as “you”. “Licensees” and - “recipients” may be individuals or organizations. - - To “modify” a work means to copy from or adapt all or part of the work in - a fashion requiring copyright permission, other than the making of an - exact copy. The resulting work is called a “modified version” of the - earlier work or a work “based on” the earlier work. - - A “covered work” means either the unmodified Program or a work based on - the Program. - - To “propagate” a work means to do anything with it that, without - permission, would make you directly or secondarily liable for - infringement under applicable copyright law, except executing it on a - computer or modifying a private copy. Propagation includes copying, - distribution (with or without modification), making available to the - public, and in some countries other activities as well. - - To “convey” a work means any kind of propagation that enables other - parties to make or receive copies. Mere interaction with a user through a - computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays “Appropriate Legal Notices” to the - extent that it includes a convenient and prominently visible feature that - (1) displays an appropriate copyright notice, and (2) tells the user that - there is no warranty for the work (except to the extent that warranties - are provided), that licensees may convey the work under this License, and - how to view a copy of this License. If the interface presents a list of - user commands or options, such as a menu, a prominent item in the list - meets this criterion. - - 1. Source Code. - - The “source code” for a work means the preferred form of the work for - making modifications to it. “Object code” means any non-source form of a - work. - - A “Standard Interface” means an interface that either is an official - standard defined by a recognized standards body, or, in the case of - interfaces specified for a particular programming language, one that is - widely used among developers working in that language. The “System - Libraries” of an executable work include anything, other than the work as - a whole, that (a) is included in the normal form of packaging a Major - Component, but which is not part of that Major Component, and (b) serves - only to enable use of the work with that Major Component, or to implement - a Standard Interface for which an implementation is available to the - public in source code form. A “Major Component”, in this context, means a - major essential component (kernel, window system, and so on) of the - specific operating system (if any) on which the executable work runs, or - a compiler used to produce the work, or an object code interpreter used - to run it. - - The “Corresponding Source” for a work in object code form means all the - source code needed to generate, install, and (for an executable work) run - the object code and to modify the work, including scripts to control - those activities. However, it does not include the work's System - Libraries, or general-purpose tools or generally available free programs - which are used unmodified in performing those activities but which are - not part of the work. For example, Corresponding Source includes - interface definition files associated with source files for the work, and - the source code for shared libraries and dynamically linked subprograms - that the work is specifically designed to require, such as by intimate - data communication or control flow between those subprograms and other - parts of the work. - - The Corresponding Source need not include anything that users can - regenerate automatically from other parts of the Corresponding Source. - - The Corresponding Source for a work in source code form is that same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of - copyright on the Program, and are irrevocable provided the stated - conditions are met. This License explicitly affirms your unlimited - permission to run the unmodified Program, subject to section 13. The - output from running a covered work is covered by this License only if the - output, given its content, constitutes a covered work. This License - acknowledges your rights of fair use or other equivalent, as provided by - copyright law. Subject to section 13, you may make, run and propagate - covered works that you do not convey, without conditions so long as your - license otherwise remains in force. You may convey covered works to - others for the sole purpose of having them make modifications exclusively - for you, or provide you with facilities for running those works, provided - that you comply with the terms of this License in conveying all - material for which you do not control copyright. Those thus making or - running the covered works for you must do so exclusively on your - behalf, under your direction and control, on terms that prohibit them - from making any copies of your copyrighted material outside their - relationship with you. - - Conveying under any other circumstances is permitted solely under the - conditions stated below. Sublicensing is not allowed; section 10 makes it - unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological - measure under any applicable law fulfilling obligations under article 11 - of the WIPO copyright treaty adopted on 20 December 1996, or similar laws - prohibiting or restricting circumvention of such measures. - - When you convey a covered work, you waive any legal power to forbid - circumvention of technological measures to the extent such circumvention is - effected by exercising rights under this License with respect to the - covered work, and you disclaim any intention to limit operation or - modification of the work as a means of enforcing, against the work's users, - your or third parties' legal rights to forbid circumvention of - technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you - receive it, in any medium, provided that you conspicuously and - appropriately publish on each copy an appropriate copyright notice; keep - intact all notices stating that this License and any non-permissive terms - added in accord with section 7 apply to the code; keep intact all notices - of the absence of any warranty; and give all recipients a copy of this - License along with the Program. You may charge any price or no price for - each copy that you convey, and you may offer support or warranty - protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to - produce it from the Program, in the form of source code under the terms - of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified it, - and giving a relevant date. - - b) The work must carry prominent notices stating that it is released - under this License and any conditions added under section 7. This - requirement modifies the requirement in section 4 to “keep intact all - notices”. - - c) You must license the entire work, as a whole, under this License to - anyone who comes into possession of a copy. This License will therefore - apply, along with any applicable section 7 additional terms, to the - whole of the work, and all its parts, regardless of how they are - packaged. This License gives no permission to license the work in any - other way, but it does not invalidate such permission if you have - separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your work - need not make them do so. - - A compilation of a covered work with other separate and independent - works, which are not by their nature extensions of the covered work, and - which are not combined with it such as to form a larger program, in or on - a volume of a storage or distribution medium, is called an “aggregate” if - the compilation and its resulting copyright are not used to limit the - access or legal rights of the compilation's users beyond what the - individual works permit. Inclusion of a covered work in an aggregate does - not cause this License to apply to the other parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms of - sections 4 and 5, provided that you also convey the machine-readable - Corresponding Source under the terms of this License, in one of these - ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium customarily - used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a written - offer, valid for at least three years and valid for as long as you - offer spare parts or customer support for that product model, to give - anyone who possesses the object code either (1) a copy of the - Corresponding Source for all the software in the product that is - covered by this License, on a durable physical medium customarily used - for software interchange, for a price no more than your reasonable cost - of physically performing this conveying of source, or (2) access to - copy the Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This alternative is - allowed only occasionally and noncommercially, and only if you received - the object code with such an offer, in accord with subsection 6b. - - d) Convey the object code by offering access from a designated place - (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to copy - the object code is a network server, the Corresponding Source may be on - a different server (operated by you or a third party) that supports - equivalent copying facilities, provided you maintain clear directions - next to the object code saying where to find the Corresponding Source. - Regardless of what server hosts the Corresponding Source, you remain - obligated to ensure that it is available for as long as needed to - satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided you - inform other peers where the object code and Corresponding Source of - the work are being offered to the general public at no charge under - subsection 6d. - - A separable portion of the object code, whose source code is excluded - from the Corresponding Source as a System Library, need not be included - in conveying the object code work. - - A “User Product” is either (1) a “consumer product”, which means any - tangible personal property which is normally used for personal, family, - or household purposes, or (2) anything designed or sold for incorporation - into a dwelling. In determining whether a product is a consumer product, - doubtful cases shall be resolved in favor of coverage. For a particular - product received by a particular user, “normally used” refers to a - typical or common use of that class of product, regardless of the status - of the particular user or of the way in which the particular user - actually uses, or expects or is expected to use, the product. A product - is a consumer product regardless of whether the product has substantial - commercial, industrial or non-consumer uses, unless such uses represent - the only significant mode of use of the product. - - “Installation Information” for a User Product means any methods, - procedures, authorization keys, or other information required to install - and execute modified versions of a covered work in that User Product from - a modified version of its Corresponding Source. The information must - suffice to ensure that the continued functioning of the modified object - code is in no case prevented or interfered with solely because - modification has been made. - - If you convey an object code work under this section in, or with, or - specifically for use in, a User Product, and the conveying occurs as part - of a transaction in which the right of possession and use of the User - Product is transferred to the recipient in perpetuity or for a fixed term - (regardless of how the transaction is characterized), the Corresponding - Source conveyed under this section must be accompanied by the - Installation Information. But this requirement does not apply if neither - you nor any third party retains the ability to install modified object - code on the User Product (for example, the work has been installed in - ROM). - - The requirement to provide Installation Information does not include a - requirement to continue to provide support service, warranty, or updates - for a work that has been modified or installed by the recipient, or for - the User Product in which it has been modified or installed. Access - to a network may be denied when the modification itself materially - and adversely affects the operation of the network or violates the - rules and protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, in - accord with this section must be in a format that is publicly documented - (and with an implementation available to the public in source code form), - and must require no special password or key for unpacking, reading or - copying. - - 7. Additional Terms. - - “Additional permissions” are terms that supplement the terms of this - License by making exceptions from one or more of its conditions. - Additional permissions that are applicable to the entire Program shall be - treated as though they were included in this License, to the extent that - they are valid under applicable law. If additional permissions apply only - to part of the Program, that part may be used separately under those - permissions, but the entire Program remains governed by this License - without regard to the additional permissions. When you convey a copy of - a covered work, you may at your option remove any additional permissions - from that copy, or from any part of it. (Additional permissions may be - written to require their own removal in certain cases when you modify the - work.) You may place additional permissions on material, added by you to - a covered work, for which you have or can give appropriate copyright - permission. - - Notwithstanding any other provision of this License, for material you add - to a covered work, you may (if authorized by the copyright holders of - that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some trade - names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that material - by anyone who conveys the material (or modified versions of it) with - contractual assumptions of liability to the recipient, for any - liability that these contractual assumptions directly impose on those - licensors and authors. - - All other non-permissive additional terms are considered “further - restrictions” within the meaning of section 10. If the Program as you - received it, or any part of it, contains a notice stating that it is - governed by this License along with a term that is a further restriction, - you may remove that term. If a license document contains a further - restriction but permits relicensing or conveying under this License, you - may add to a covered work material governed by the terms of that license - document, provided that the further restriction does not survive such - relicensing or conveying. - - If you add terms to a covered work in accord with this section, you must - place, in the relevant source files, a statement of the additional terms - that apply to those files, or a notice indicating where to find the - applicable terms. Additional terms, permissive or non-permissive, may be - stated in the form of a separately written license, or stated as - exceptions; the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly - provided under this License. Any attempt otherwise to propagate or modify - it is void, and will automatically terminate your rights under this - License (including any patent licenses granted under the third paragraph - of section 11). - - However, if you cease all violation of this License, then your license - from a particular copyright holder is reinstated (a) provisionally, - unless and until the copyright holder explicitly and finally terminates - your license, and (b) permanently, if the copyright holder fails to - notify you of the violation by some reasonable means prior to 60 days - after the cessation. - - Moreover, your license from a particular copyright holder is reinstated - permanently if the copyright holder notifies you of the violation by some - reasonable means, this is the first time you have received notice of - violation of this License (for any work) from that copyright holder, and - you cure the violation prior to 30 days after your receipt of the notice. - - Termination of your rights under this section does not terminate the - licenses of parties who have received copies or rights from you under - this License. If your rights have been terminated and not permanently - reinstated, you do not qualify to receive new licenses for the same - material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or run a - copy of the Program. Ancillary propagation of a covered work occurring - solely as a consequence of using peer-to-peer transmission to receive a - copy likewise does not require acceptance. However, nothing other than - this License grants you permission to propagate or modify any covered - work. These actions infringe copyright if you do not accept this License. - Therefore, by modifying or propagating a covered work, you indicate your - acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically receives - a license from the original licensors, to run, modify and propagate that - work, subject to this License. You are not responsible for enforcing - compliance by third parties with this License. - - An “entity transaction” is a transaction transferring control of an - organization, or substantially all assets of one, or subdividing an - organization, or merging organizations. If propagation of a covered work - results from an entity transaction, each party to that transaction who - receives a copy of the work also receives whatever licenses to the work - the party's predecessor in interest had or could give under the previous - paragraph, plus a right to possession of the Corresponding Source of the - work from the predecessor in interest, if the predecessor has it or can - get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the rights - granted or affirmed under this License. For example, you may not impose a - license fee, royalty, or other charge for exercise of rights granted - under this License, and you may not initiate litigation (including a - cross-claim or counterclaim in a lawsuit) alleging that any patent claim - is infringed by making, using, selling, offering for sale, or importing - the Program or any portion of it. - - 11. Patents. - - A “contributor” is a copyright holder who authorizes use under this - License of the Program or a work on which the Program is based. The work - thus licensed is called the contributor's “contributor version”. - - A contributor's “essential patent claims” are all patent claims owned or - controlled by the contributor, whether already acquired or hereafter - acquired, that would be infringed by some manner, permitted by this - License, of making, using, or selling its contributor version, but do not - include claims that would be infringed only as a consequence of further - modification of the contributor version. For purposes of this definition, - “control” includes the right to grant patent sublicenses in a manner - consistent with the requirements of this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free - patent license under the contributor's essential patent claims, to make, - use, sell, offer for sale, import and otherwise run, modify and propagate - the contents of its contributor version. - - In the following three paragraphs, a “patent license” is any express - agreement or commitment, however denominated, not to enforce a patent - (such as an express permission to practice a patent or covenant not to - sue for patent infringement). To “grant” such a patent license to a party - means to make such an agreement or commitment not to enforce a patent - against the party. - - If you convey a covered work, knowingly relying on a patent license, and - the Corresponding Source of the work is not available for anyone to copy, - free of charge and under the terms of this License, through a publicly - available network server or other readily accessible means, then you must - either (1) cause the Corresponding Source to be so available, or (2) - arrange to deprive yourself of the benefit of the patent license for this - particular work, or (3) arrange, in a manner consistent with the - requirements of this License, to extend the patent license to downstream - recipients. “Knowingly relying” means you have actual knowledge that, but - for the patent license, your conveying the covered work in a country, or - your recipient's use of the covered work in a country, would infringe - one or more identifiable patents in that country that you have reason - to believe are valid. - - If, pursuant to or in connection with a single transaction or - arrangement, you convey, or propagate by procuring conveyance of, a - covered work, and grant a patent license to some of the parties receiving - the covered work authorizing them to use, propagate, modify or convey a - specific copy of the covered work, then the patent license you grant is - automatically extended to all recipients of the covered work and works - based on it. - - A patent license is “discriminatory” if it does not include within the - scope of its coverage, prohibits the exercise of, or is conditioned on - the non-exercise of one or more of the rights that are specifically - granted under this License. You may not convey a covered work if you are - a party to an arrangement with a third party that is in the business of - distributing software, under which you make payment to the third party - based on the extent of your activity of conveying the work, and under - which the third party grants, to any of the parties who would receive the - covered work from you, a discriminatory patent license (a) in connection - with copies of the covered work conveyed by you (or copies made from - those copies), or (b) primarily for and in connection with specific - products or compilations that contain the covered work, unless you - entered into that arrangement, or that patent license was granted, prior - to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting any - implied license or other defenses to infringement that may otherwise be - available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or - otherwise) that contradict the conditions of this License, they do not - excuse you from the conditions of this License. If you cannot use, - propagate or convey a covered work so as to satisfy simultaneously your - obligations under this License and any other pertinent obligations, then - as a consequence you may not use, propagate or convey it at all. For - example, if you agree to terms that obligate you to collect a royalty for - further conveying from those to whom you convey the Program, the only way - you could satisfy both those terms and this License would be to refrain - entirely from conveying the Program. - - 13. Offering the Program as a Service. - - If you make the functionality of the Program or a modified version - available to third parties as a service, you must make the Service Source - Code available via network download to everyone at no charge, under the - terms of this License. Making the functionality of the Program or - modified version available to third parties as a service includes, - without limitation, enabling third parties to interact with the - functionality of the Program or modified version remotely through a - computer network, offering a service the value of which entirely or - primarily derives from the value of the Program or modified version, or - offering a service that accomplishes for users the primary purpose of the - Program or modified version. - - “Service Source Code” means the Corresponding Source for the Program or - the modified version, and the Corresponding Source for all programs that - you use to make the Program or modified version available as a service, - including, without limitation, management software, user interfaces, - application program interfaces, automation software, monitoring software, - backup software, storage software and hosting software, all such that a - user could run an instance of the service using the Service Source Code - you make available. - - 14. Revised Versions of this License. - - MongoDB, Inc. may publish revised and/or new versions of the Server Side - Public License from time to time. Such new versions will be similar in - spirit to the present version, but may differ in detail to address new - problems or concerns. - - Each version is given a distinguishing version number. If the Program - specifies that a certain numbered version of the Server Side Public - License “or any later version” applies to it, you have the option of - following the terms and conditions either of that numbered version or of - any later version published by MongoDB, Inc. If the Program does not - specify a version number of the Server Side Public License, you may - choose any version ever published by MongoDB, Inc. - - If the Program specifies that a proxy can decide which future versions of - the Server Side Public License can be used, that proxy's public statement - of acceptance of a version permanently authorizes you to choose that - version for the Program. - - Later license versions may give you additional or different permissions. - However, no additional obligations are imposed on any author or copyright - holder as a result of your choosing to follow a later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY - APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT - HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUT WARRANTY - OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, - THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM - IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF - ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING - WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS - THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING - ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF - THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO - LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU - OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER - PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE - POSSIBILITY OF SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided above - cannot be given local legal effect according to their terms, reviewing - courts shall apply local law that most closely approximates an absolute - waiver of all civil liability in connection with the Program, unless a - warranty or assumption of liability accompanies a copy of the Program in - return for a fee. - - END OF TERMS AND CONDITIONS diff --git a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/MPL-2 b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/MPL-2 deleted file mode 100644 index 197b2ffd..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/MPL-2 +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/README b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/README deleted file mode 100644 index 97f1dc72..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/README +++ /dev/null @@ -1,87 +0,0 @@ -MongoDB README - -Welcome to MongoDB! - -COMPONENTS - - mongod - The database server. - mongos - Sharding router. - mongo - The database shell (uses interactive javascript). - -UTILITIES - - install_compass - Installs MongoDB Compass for your platform. - -BUILDING - - See docs/building.md. - -RUNNING - - For command line options invoke: - - $ ./mongod --help - - To run a single server database: - - $ sudo mkdir -p /data/db - $ ./mongod - $ - $ # The mongo javascript shell connects to localhost and test database by default: - $ ./mongo - > help - -INSTALLING COMPASS - - You can install compass using the install_compass script packaged with MongoDB: - - $ ./install_compass - - This will download the appropriate MongoDB Compass package for your platform - and install it. - -DRIVERS - - Client drivers for most programming languages are available at - https://docs.mongodb.com/manual/applications/drivers/. Use the shell - ("mongo") for administrative tasks. - -BUG REPORTS - - See https://github.com/mongodb/mongo/wiki/Submit-Bug-Reports. - -PACKAGING - - Packages are created dynamically by the package.py script located in the - buildscripts directory. This will generate RPM and Debian packages. - -DOCUMENTATION - - https://docs.mongodb.com/manual/ - -CLOUD HOSTED MONGODB - - https://www.mongodb.com/cloud/atlas - -FORUMS - - https://community.mongodb.com - - A forum for technical questions about using MongoDB. - - https://community.mongodb.com/c/server-dev - - A forum for technical questions about building and developing MongoDB. - -LEARN MONGODB - - https://university.mongodb.com/ - -LICENSE - - MongoDB is free and open-source. Versions released prior to October 16, - 2018 are published under the AGPL. All versions released after October - 16, 2018, including patch fixes for prior versions, are published under - the Server Side Public License (SSPL) v1. See individual files for - details. - diff --git a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES deleted file mode 100644 index 8c9e17e3..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/community-server/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,1568 +0,0 @@ -MongoDB uses third-party libraries or other resources that may -be distributed under licenses different than the MongoDB software. - -In the event that we accidentally failed to list a required notice, -please bring it to our attention through any of the ways detailed here : - - mongodb-dev@googlegroups.com - -The attached notices are provided for information only. - -For any licenses that require disclosure of source, sources are available at -https://github.com/mongodb/mongo. - - -1) License Notice for Boost ---------------------------- - -http://www.boost.org/LICENSE_1_0.txt - -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - -3) License Notice for PCRE --------------------------- - -http://www.pcre.org/licence.txt - -PCRE LICENCE ------------- - -PCRE is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - -Release 7 of PCRE is distributed under the terms of the "BSD" licence, as -specified below. The documentation for PCRE, supplied in the "doc" -directory, is distributed under the same terms as the software itself. - -The basic library functions are written in C and are freestanding. Also -included in the distribution is a set of C++ wrapper functions. - - -THE BASIC LIBRARY FUNCTIONS ---------------------------- - -Written by: Philip Hazel -Email local part: ph10 -Email domain: cam.ac.uk - -University of Cambridge Computing Service, -Cambridge, England. - -Copyright (c) 1997-2008 University of Cambridge -All rights reserved. - - -THE C++ WRAPPER FUNCTIONS -------------------------- - -Contributed by: Google Inc. - -Copyright (c) 2007-2008, Google Inc. -All rights reserved. - - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - - -4) License notice for Aladdin MD5 ---------------------------------- - -Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -L. Peter Deutsch -ghost@aladdin.com - -5) License notice for Snappy - http://code.google.com/p/snappy/ ---------------------------------- - Copyright 2005 and onwards Google Inc. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - A light-weight compression algorithm. It is designed for speed of - compression and decompression, rather than for the utmost in space - savings. - - For getting better compression ratios when you are compressing data - with long repeated sequences or compressing data that is similar to - other data, while still compressing fast, you might look at first - using BMDiff and then compressing the output of BMDiff with - Snappy. - -6) License notice for Google Perftools (TCMalloc utility) ---------------------------------- -New BSD License - -Copyright (c) 1998-2006, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products - derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -7) License notice for Linenoise -------------------------------- - - Copyright (c) 2010, Salvatore Sanfilippo - Copyright (c) 2010, Pieter Noordhuis - - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of Redis nor the names of its contributors may be used - to endorse or promote products derived from this software without - specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -8) License notice for S2 Geometry Library ------------------------------------------ - Copyright 2005 Google Inc. All Rights Reserved. - - 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. - -9) License notice for MurmurHash --------------------------------- - - Copyright (c) 2010-2012 Austin Appleby - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -10) License notice for Snowball - Copyright (c) 2001, Dr Martin Porter - All rights reserved. - -THE "BSD" LICENCE ------------------ - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the name of Google - Inc. nor the names of their contributors may be used to endorse or - promote products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -11) License notice for yaml-cpp -------------------------------- - -Copyright (c) 2008 Jesse Beder. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -12) License notice for zlib ---------------------------- - -http://www.zlib.net/zlib_license.html - -zlib.h -- interface of the 'zlib' general purpose compression library -version 1.2.8, April 28th, 2013 - -Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Jean-loup Gailly Mark Adler -jloup@gzip.org madler@alumni.caltech.edu - - -13) License notice for 3rd party software included in the WiredTiger library ----------------------------------------------------------------------------- - -http://source.wiredtiger.com/license.html - -WiredTiger Distribution Files | Copyright Holder | License ------------------------------ | ----------------------------------- | ---------------------- -src/include/bitstring.i | University of California, Berkeley | BSD-3-Clause License -src/include/queue.h | University of California, Berkeley | BSD-3-Clause License -src/os_posix/os_getopt.c | University of California, Berkeley | BSD-3-Clause License -src/support/hash_city.c | Google, Inc. | The MIT License -src/support/hash_fnv.c | Authors | Public Domain - - -Other optional 3rd party software included in the WiredTiger distribution is removed by MongoDB. - - -BSD-3-CLAUSE LICENSE --------------------- - -http://www.opensource.org/licenses/BSD-3-Clause - -Copyright (c) 1987, 1989, 1991, 1993, 1994 - The Regents of the University of California. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. -4. Neither the name of the University nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -SUCH DAMAGE. - - -THE MIT LICENSE ---------------- - -http://www.opensource.org/licenses/MIT - -Copyright (c) 2011 Google, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - -14) License Notice for SpiderMonkey ------------------------------------ - -|------------------------------------------------|------------------|---------------| -| SpiderMonkey Distribution Files | Copyright Holder | License | -|------------------------------------------------|------------------|---------------| -| js/src/jit/shared/AssemblerBuffer-x86-shared.h | Apple, Inc | BSD-2-Clause | -| js/src/jit/shared/BaseAssembler-x86-shared.h | | | -|------------------------------------------------|------------------|---------------| -| js/src/builtin/ | Google, Inc | BSD-3-Clause | -| js/src/irregexp/ | | | -| js/src/jit/arm/ | | | -| js/src/jit/mips/ | | | -| mfbt/double-conversion/ | | | -|------------------------------------------------|------------------|---------------| -| intl/icu/source/common/unicode/ | IBM, Inc | ICU | -|------------------------------------------------|------------------|---------------| -| js/src/asmjs/ | Mozilla, Inc | Apache2 | -|------------------------------------------------|------------------|---------------| -| js/public/ | Mozilla, Inc | MPL2 | -| js/src/ | | | -| mfbt | | | -|------------------------------------------------|------------------|---------------| -| js/src/vm/Unicode.cpp | None | Public Domain | -|------------------------------------------------|------------------|---------------| -| mfbt/lz4.c | Yann Collet | BSD-2-Clause | -| mfbt/lz4.h | | | -|------------------------------------------------|------------------|---------------| - -Other optional 3rd party software included in the SpiderMonkey distribution is removed by MongoDB. - - -Apple, Inc: BSD-2-Clause ------------------------- - -Copyright (C) 2008 Apple Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY -OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -Google, Inc: BSD-3-Clause -------------------------- - -Copyright 2012 the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -ICU License - ICU 1.8.1 and later ---------------------------------- - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2012 International Business Machines Corporation and -others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, provided that the above copyright notice(s) and this -permission notice appear in all copies of the Software and that both the -above copyright notice(s) and this permission notice appear in supporting -documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE -BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, -OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -Except as contained in this notice, the name of a copyright holder shall -not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization of the -copyright holder. - -All trademarks and registered trademarks mentioned herein are the property -of their respective owners. - - -Mozilla, Inc: Apache 2 ----------------------- - -Copyright 2014 Mozilla Foundation - -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. - - -Mozilla, Inc: MPL 2 -------------------- - -Copyright 2014 Mozilla Foundation - -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - - -Public Domain -------------- - -Any copyright is dedicated to the Public Domain. -http://creativecommons.org/licenses/publicdomain/ - - -LZ4: BSD-2-Clause ------------------ - -Copyright (C) 2011-2014, Yann Collet. -BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -You can contact the author at : -- LZ4 source repository : http://code.google.com/p/lz4/ -- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c - -15) License Notice for Intel DFP Math Library ---------------------------------------------- - -Copyright (c) 2011, Intel Corp. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - his list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Intel Corporation nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. -IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -16) License Notice for Unicode Data ------------------------------------ - -Copyright © 1991-2015 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -17 ) License Notice for Valgrind.h ----------------------------------- - ----------------------------------------------------------------- - -Notice that the following BSD-style license applies to this one -file (valgrind.h) only. The rest of Valgrind is licensed under the -terms of the GNU General Public License, version 2, unless -otherwise indicated. See the COPYING file in the source -distribution for details. - ----------------------------------------------------------------- - -This file is part of Valgrind, a dynamic binary instrumentation -framework. - -Copyright (C) 2000-2015 Julian Seward. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions -are met: - -1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - -2. The origin of this software must not be misrepresented; you must - not claim that you wrote the original software. If you use this - software in a product, an acknowledgment in the product - documentation would be appreciated but is not required. - -3. Altered source versions must be plainly marked as such, and must - not be misrepresented as being the original software. - -4. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS -OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------- - -Notice that the above BSD-style license applies to this one file -(valgrind.h) only. The entire rest of Valgrind is licensed under -the terms of the GNU General Public License, version 2. See the -COPYING file in the source distribution for details. - ----------------------------------------------------------------- - -18) License notice for ICU4C ----------------------------- - -ICU License - ICU 1.8.1 and later - -COPYRIGHT AND PERMISSION NOTICE - -Copyright (c) 1995-2016 International Business Machines Corporation and others - -All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, and/or sell copies of the Software, and to permit persons -to whom the Software is furnished to do so, provided that the above -copyright notice(s) and this permission notice appear in all copies of -the Software and that both the above copyright notice(s) and this -permission notice appear in supporting documentation. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY -SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER -RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF -CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, use -or other dealings in this Software without prior written authorization -of the copyright holder. - - -All trademarks and registered trademarks mentioned herein are the -property of their respective owners. - ---------------------- - -Third-Party Software Licenses - -This section contains third-party software notices and/or additional -terms for licensed third-party software components included within ICU -libraries. - -1. Unicode Data Files and Software - -COPYRIGHT AND PERMISSION NOTICE - -Copyright © 1991-2016 Unicode, Inc. All rights reserved. -Distributed under the Terms of Use in -http://www.unicode.org/copyright.html. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Unicode data files and any associated documentation -(the "Data Files") or Unicode software and any associated documentation -(the "Software") to deal in the Data Files or Software -without restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, and/or sell copies of -the Data Files or Software, and to permit persons to whom the Data Files -or Software are furnished to do so, provided that -(a) this copyright and permission notice appear with all copies -of the Data Files or Software, -(b) this copyright and permission notice appear in associated -documentation, and -(c) there is clear notice in each modified Data File or in the Software -as well as in the documentation associated with the Data File(s) or -Software that the data or software has been modified. - -THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT OF THIRD PARTY RIGHTS. -IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS -NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL -DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THE DATA FILES OR SOFTWARE. - -Except as contained in this notice, the name of a copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in these Data Files or Software without prior -written authorization of the copyright holder. - -2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt) - - # The Google Chrome software developed by Google is licensed under - # the BSD license. Other software included in this distribution is - # provided under other licenses, as set forth below. - # - # The BSD License - # http://opensource.org/licenses/bsd-license.php - # Copyright (C) 2006-2008, Google Inc. - # - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions are met: - # - # Redistributions of source code must retain the above copyright notice, - # this list of conditions and the following disclaimer. - # Redistributions in binary form must reproduce the above - # copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided with - # the distribution. - # Neither the name of Google Inc. nor the names of its - # contributors may be used to endorse or promote products derived from - # this software without specific prior written permission. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - # - # - # The word list in cjdict.txt are generated by combining three word lists - # listed below with further processing for compound word breaking. The - # frequency is generated with an iterative training against Google web - # corpora. - # - # * Libtabe (Chinese) - # - https://sourceforge.net/project/?group_id=1519 - # - Its license terms and conditions are shown below. - # - # * IPADIC (Japanese) - # - http://chasen.aist-nara.ac.jp/chasen/distribution.html - # - Its license terms and conditions are shown below. - # - # ---------COPYING.libtabe ---- BEGIN-------------------- - # - # /* - # * Copyrighy (c) 1999 TaBE Project. - # * Copyright (c) 1999 Pai-Hsiang Hsiao. - # * All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the TaBE Project nor the names of its - # * contributors may be used to endorse or promote products derived - # * from this software without specific prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # /* - # * Copyright (c) 1999 Computer Systems and Communication Lab, - # * Institute of Information Science, Academia - # * Sinica. All rights reserved. - # * - # * Redistribution and use in source and binary forms, with or without - # * modification, are permitted provided that the following conditions - # * are met: - # * - # * . Redistributions of source code must retain the above copyright - # * notice, this list of conditions and the following disclaimer. - # * . Redistributions in binary form must reproduce the above copyright - # * notice, this list of conditions and the following disclaimer in - # * the documentation and/or other materials provided with the - # * distribution. - # * . Neither the name of the Computer Systems and Communication Lab - # * nor the names of its contributors may be used to endorse or - # * promote products derived from this software without specific - # * prior written permission. - # * - # * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - # * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # * OF THE POSSIBILITY OF SUCH DAMAGE. - # */ - # - # Copyright 1996 Chih-Hao Tsai @ Beckman Institute, - # University of Illinois - # c-tsai4@uiuc.edu http://casper.beckman.uiuc.edu/~c-tsai4 - # - # ---------------COPYING.libtabe-----END-------------------------------- - # - # - # ---------------COPYING.ipadic-----BEGIN------------------------------- - # - # Copyright 2000, 2001, 2002, 2003 Nara Institute of Science - # and Technology. All Rights Reserved. - # - # Use, reproduction, and distribution of this software is permitted. - # Any copy of this software, whether in its original form or modified, - # must include both the above copyright notice and the following - # paragraphs. - # - # Nara Institute of Science and Technology (NAIST), - # the copyright holders, disclaims all warranties with regard to this - # software, including all implied warranties of merchantability and - # fitness, in no event shall NAIST be liable for - # any special, indirect or consequential damages or any damages - # whatsoever resulting from loss of use, data or profits, whether in an - # action of contract, negligence or other tortuous action, arising out - # of or in connection with the use or performance of this software. - # - # A large portion of the dictionary entries - # originate from ICOT Free Software. The following conditions for ICOT - # Free Software applies to the current dictionary as well. - # - # Each User may also freely distribute the Program, whether in its - # original form or modified, to any third party or parties, PROVIDED - # that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear - # on, or be attached to, the Program, which is distributed substantially - # in the same form as set out herein and that such intended - # distribution, if actually made, will neither violate or otherwise - # contravene any of the laws and regulations of the countries having - # jurisdiction over the User or the intended distribution itself. - # - # NO WARRANTY - # - # The program was produced on an experimental basis in the course of the - # research and development conducted during the project and is provided - # to users as so produced on an experimental basis. Accordingly, the - # program is provided without any warranty whatsoever, whether express, - # implied, statutory or otherwise. The term "warranty" used herein - # includes, but is not limited to, any warranty of the quality, - # performance, merchantability and fitness for a particular purpose of - # the program and the nonexistence of any infringement or violation of - # any right of any third party. - # - # Each user of the program will agree and understand, and be deemed to - # have agreed and understood, that there is no warranty whatsoever for - # the program and, accordingly, the entire risk arising from or - # otherwise connected with the program is assumed by the user. - # - # Therefore, neither ICOT, the copyright holder, or any other - # organization that participated in or was otherwise related to the - # development of the program and their respective officials, directors, - # officers and other employees shall be held liable for any and all - # damages, including, without limitation, general, special, incidental - # and consequential damages, arising out of or otherwise in connection - # with the use or inability to use the program or any product, material - # or result produced or otherwise obtained by using the program, - # regardless of whether they have been advised of, or otherwise had - # knowledge of, the possibility of such damages at any time during the - # project or thereafter. Each user will be deemed to have agreed to the - # foregoing by his or her commencement of use of the program. The term - # "use" as used herein includes, but is not limited to, the use, - # modification, copying and distribution of the program and the - # production of secondary products from the program. - # - # In the case where the program, whether in its original form or - # modified, was distributed or delivered to or received by a user from - # any person, organization or entity other than ICOT, unless it makes or - # grants independently of ICOT any specific warranty to the user in - # writing, such person, organization or entity, will also be exempted - # from and not be held liable to the user for any such damages as noted - # above as far as the program is concerned. - # - # ---------------COPYING.ipadic-----END---------------------------------- - -3. Lao Word Break Dictionary Data (laodict.txt) - - # Copyright (c) 2013 International Business Machines Corporation - # and others. All Rights Reserved. - # - # Project: http://code.google.com/p/lao-dictionary/ - # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt - # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt - # (copied below) - # - # This file is derived from the above dictionary, with slight - # modifications. - # ---------------------------------------------------------------------- - # Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell. - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, - # are permitted provided that the following conditions are met: - # - # - # Redistributions of source code must retain the above copyright notice, this - # list of conditions and the following disclaimer. Redistributions in - # binary form must reproduce the above copyright notice, this list of - # conditions and the following disclaimer in the documentation and/or - # other materials provided with the distribution. - # - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - # OF THE POSSIBILITY OF SUCH DAMAGE. - # -------------------------------------------------------------------------- - -4. Burmese Word Break Dictionary Data (burmesedict.txt) - - # Copyright (c) 2014 International Business Machines Corporation - # and others. All Rights Reserved. - # - # This list is part of a project hosted at: - # github.com/kanyawtech/myanmar-karen-word-lists - # - # -------------------------------------------------------------------------- - # Copyright (c) 2013, LeRoy Benjamin Sharon - # All rights reserved. - # - # Redistribution and use in source and binary forms, with or without - # modification, are permitted provided that the following conditions - # are met: Redistributions of source code must retain the above - # copyright notice, this list of conditions and the following - # disclaimer. Redistributions in binary form must reproduce the - # above copyright notice, this list of conditions and the following - # disclaimer in the documentation and/or other materials provided - # with the distribution. - # - # Neither the name Myanmar Karen Word Lists, nor the names of its - # contributors may be used to endorse or promote products derived - # from this software without specific prior written permission. - # - # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND - # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, - # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS - # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - # TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF - # THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - # SUCH DAMAGE. - # -------------------------------------------------------------------------- - -5. Time Zone Database - - ICU uses the public domain data and code derived from Time Zone -Database for its time zone support. The ownership of the TZ database -is explained in BCP 175: Procedure for Maintaining the Time Zone -Database section 7. - - # 7. Database Ownership - # - # The TZ database itself is not an IETF Contribution or an IETF - # document. Rather it is a pre-existing and regularly updated work - # that is in the public domain, and is intended to remain in the - # public domain. Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do - # not apply to the TZ Database or contributions that individuals make - # to it. Should any claims be made and substantiated against the TZ - # Database, the organization that is providing the IANA - # Considerations defined in this RFC, under the memorandum of - # understanding with the IETF, currently ICANN, may act in accordance - # with all competent court orders. No ownership claims will be made - # by ICANN or the IETF Trust on the database or the code. Any person - # making a contribution to the database or code waives all rights to - # future claims in that contribution or in the TZ Database. - -19) License notice for timelib ------------------------------- - -The MIT License (MIT) - -Copyright (c) 2015-2017 Derick Rethans -Copyright (c) 2017 MongoDB, Inc - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -20) License notice for windows dirent implementation ----------------------------------------------------- - - * Dirent interface for Microsoft Visual Studio - * Version 1.21 - * - * Copyright (C) 2006-2012 Toni Ronkko - * This file is part of dirent. Dirent may be freely distributed - * under the MIT license. For all details and documentation, see - * https://github.com/tronkko/dirent - - - 21) License notice for abseil-cpp ----------------------------- - - Copyright (c) Google Inc. - - 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. - - 22) License notice for Zstandard ----------------------------- - - BSD License - - For Zstandard software - - Copyright (c) 2016-present, Facebook, Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, - are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - * Neither the name Facebook nor the names of its contributors may be used to - endorse or promote products derived from this software without specific - prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR - ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 23) License notice for ASIO ----------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 24) License notice for MPark.Variant -------------------------------------- -Boost Software License - Version 1.0 - August 17th, 2003 - -Permission is hereby granted, free of charge, to any person or organization -obtaining a copy of the software and accompanying documentation covered by -this license (the "Software") to use, reproduce, display, distribute, -execute, and transmit the Software, and to prepare derivative works of the -Software, and to permit third-parties to whom the Software is furnished to -do so, all subject to the following: - -The copyright notices in the Software and this entire statement, including -the above license grant, this restriction and the following disclaimer, -must be included in all copies of the Software, in whole or in part, and -all derivative works of the Software, unless such copies or derivative -works are solely in the form of machine-executable object code generated by -a source language processor. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT -SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE -FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. - - 25) License notice for fmt ---------------------------- - -Copyright (c) 2012 - present, Victor Zverovich -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright notice, this - list of conditions and the following disclaimer in the documentation and/or other - materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - 26) License notice for SafeInt ---------------------------- - -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. - -MIT License - -Copyright (c) 2018 Microsoft - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - 27) License Notice for Raft TLA+ Specification ------------------------------------------------ - -https://github.com/ongardie/dissertation/blob/master/LICENSE - -Copyright 2014 Diego Ongaro. - -Some of our TLA+ specifications are based on the Raft TLA+ specification by Diego Ongaro. - -End diff --git a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md deleted file mode 100644 index 550ae4ed..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/LICENSE.md +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2014 MongoDB, Inc. - -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/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/README.md b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/README.md deleted file mode 100644 index e60e0cd0..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/README.md +++ /dev/null @@ -1,72 +0,0 @@ -MongoDB Tools -=================================== - - - **bsondump** - _display BSON files in a human-readable format_ - - **mongoimport** - _Convert data from JSON, TSV or CSV and insert them into a collection_ - - **mongoexport** - _Write an existing collection to CSV or JSON format_ - - **mongodump/mongorestore** - _Dump MongoDB backups to disk in .BSON format, or restore them to a live database_ - - **mongostat** - _Monitor live MongoDB servers, replica sets, or sharded clusters_ - - **mongofiles** - _Read, write, delete, or update files in [GridFS](http://docs.mongodb.org/manual/core/gridfs/)_ - - **mongotop** - _Monitor read/write activity on a mongo server_ - - -Report any bugs, improvements, or new feature requests at https://jira.mongodb.org/browse/TOOLS - -Building Tools ---------------- - -We currently build the tools with Go version 1.15. Other Go versions may work but they are untested. - -Using `go get` to directly build the tools will not work. To build them, it's recommended to first clone this repository: - -``` -git clone https://github.com/mongodb/mongo-tools -cd mongo-tools -``` - -Then run `./make build` to build all the tools, placing them in the `bin` directory inside the repository. - -You can also build a subset of the tools using the `-tools` option. For example, `./make build -tools=mongodump,mongorestore` builds only `mongodump` and `mongorestore`. - -To use the build/test scripts in this repository, you **_must_** set GOROOT to your Go root directory. This may depend on how you installed Go. - -``` -export GOROOT=/usr/local/go -``` - -Updating Dependencies ---------------- -Starting with version 100.3.1, the tools use `go mod` to manage dependencies. All dependencies are listed in the `go.mod` file and are directly vendored in the `vendor` directory. - -In order to make changes to dependencies, you first need to change the `go.mod` file. You can manually edit that file to add/update/remove entries, or you can run the following in the repository directory: - -``` -go mod edit -require=@ # for adding or updating a dependency -go mod edit -droprequire= # for removing a dependency -``` - -Then run `go mod vendor -v` to reconstruct the `vendor` directory to match the changed `go.mod` file. - -Optionally, run `go mod tidy -v` to ensure that the `go.mod` file matches the `mongo-tools` source code. - -Contributing ---------------- -See our [Contributor's Guide](CONTRIBUTING.md). - -Documentation ---------------- -See the MongoDB packages [documentation](https://docs.mongodb.org/database-tools/). - -For documentation on older versions of the MongoDB, reference that version of the [MongoDB Server Manual](docs.mongodb.com/manual): - -- [MongoDB 4.2 Tools](https://docs.mongodb.org/v4.2/reference/program) -- [MongoDB 4.0 Tools](https://docs.mongodb.org/v4.0/reference/program) -- [MongoDB 3.6 Tools](https://docs.mongodb.org/v3.6/reference/program) - -Adding New Platforms Support ---------------- -See our [Adding New Platform Support Guide](PLATFORMSUPPORT.md). - -Vendoring the Change into Server Repo ---------------- -See our [Vendor the Change into Server Repo](SERVERVENDORING.md). diff --git a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES b/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES deleted file mode 100644 index 3d75e64b..00000000 --- a/Mongo2Go.4.1.0/tools/mongodb-windows-4.4.4-database-tools-100.3.1/database-tools/THIRD-PARTY-NOTICES +++ /dev/null @@ -1,3319 +0,0 @@ ---------------------------------------------------------------------- -License notice for hashicorp/go-rootcerts ---------------------------------------------------------------------- - -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. "Contributor" - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. "Contributor Version" - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the terms of - a Secondary License. - -1.6. "Executable Form" - - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - - means a work that combines Covered Software with other material, in a - separate file or files, that is not Covered Software. - -1.8. "License" - - means this document. - -1.9. "Licensable" - - means having the right to grant, to the maximum extent possible, whether - at the time of the initial grant or subsequently, any and all of the - rights conveyed by this License. - -1.10. "Modifications" - - means any of the following: - - a. any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. "Patent Claims" of a Contributor - - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the License, - by the making, using, selling, offering for sale, having made, import, - or transfer of either its Contributions or its Contributor Version. - -1.12. "Secondary License" - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. "Source Code Form" - - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution - become effective for each Contribution on the date the Contributor first - distributes such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under - this License. No additional rights or licenses will be implied from the - distribution or licensing of Covered Software under this License. - Notwithstanding Section 2.1(b) above, no patent license is granted by a - Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of - its Contributions. - - This License does not grant any rights in the trademarks, service marks, - or logos of any Contributor (except as may be necessary to comply with - the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this - License (see Section 10.2) or under the terms of a Secondary License (if - permitted under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its - Contributions are its original creation(s) or it has sufficient rights to - grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under - applicable copyright doctrines of fair use, fair dealing, or other - equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under - the terms of this License. You must inform recipients that the Source - Code Form of the Covered Software is governed by the terms of this - License, and how they can obtain a copy of this License. You may not - attempt to alter or restrict the recipients' rights in the Source Code - Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter the - recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for - the Covered Software. If the Larger Work is a combination of Covered - Software with a work governed by one or more Secondary Licenses, and the - Covered Software is not Incompatible With Secondary Licenses, this - License permits You to additionally distribute such Covered Software - under the terms of such Secondary License(s), so that the recipient of - the Larger Work may, at their option, further distribute the Covered - Software under the terms of either this License or such Secondary - License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices - (including copyright notices, patent notices, disclaimers of warranty, or - limitations of liability) contained within the Source Code Form of the - Covered Software, except that You may alter any license notices to the - extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on - behalf of any Contributor. You must make it absolutely clear that any - such warranty, support, indemnity, or liability obligation is offered by - You alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, - judicial order, or regulation then You must: (a) comply with the terms of - this License to the maximum extent possible; and (b) describe the - limitations and the code they affect. Such description must be placed in a - text file included with all distributions of the Covered Software under - this License. Except to the extent prohibited by statute or regulation, - such description must be sufficiently detailed for a recipient of ordinary - skill to be able to understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing - basis, if such Contributor fails to notify You of the non-compliance by - some reasonable means prior to 60 days after You have come back into - compliance. Moreover, Your grants from a particular Contributor are - reinstated on an ongoing basis if such Contributor notifies You of the - non-compliance by some reasonable means, this is the first time You have - received notice of non-compliance with this License from such - Contributor, and You become compliant prior to 30 days after Your receipt - of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, - counter-claims, and cross-claims) alleging that a Contributor Version - directly or indirectly infringes any patent, then the rights granted to - You by any and all Contributors for the Covered Software under Section - 2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an "as is" basis, - without warranty of any kind, either expressed, implied, or statutory, - including, without limitation, warranties that the Covered Software is free - of defects, merchantable, fit for a particular purpose or non-infringing. - The entire risk as to the quality and performance of the Covered Software - is with You. Should any Covered Software prove defective in any respect, - You (not any Contributor) assume the cost of any necessary servicing, - repair, or correction. This disclaimer of warranty constitutes an essential - part of this License. No use of any Covered Software is authorized under - this License except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from - such party's negligence to the extent applicable law prohibits such - limitation. Some jurisdictions do not allow the exclusion or limitation of - incidental or consequential damages, so this exclusion and limitation may - not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts - of a jurisdiction where the defendant maintains its principal place of - business and such litigation shall be governed by laws of that - jurisdiction, without reference to its conflict-of-law provisions. Nothing - in this Section shall prevent a party's ability to bring cross-claims or - counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. Any law or regulation which provides that - the language of a contract shall be construed against the drafter shall not - be used to construe this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version - of the License under which You originally received the Covered Software, - or under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a - modified version of this License if you rename the license and remove - any references to the name of the license steward (except to note that - such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary - Licenses If You choose to distribute Source Code Form that is - Incompatible With Secondary Licenses under the terms of this version of - the License, the notice described in Exhibit B of this License must be - attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, -then You may include the notice in a location (such as a LICENSE file in a -relevant directory) where a recipient would be likely to look for such a -notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice - - This Source Code Form is "Incompatible - With Secondary Licenses", as defined by - the Mozilla Public License, v. 2.0. - ---------------------------------------------------------------------- -License notice for JSON and CSV code from github.com/golang/go ---------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/escaper ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Lucas Morales - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/llmgo/bson ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/10gen/openssl ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/3rf/mongo-lint ----------------------------------------------------------------------- - -Copyright (c) 2013 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/go-stack/stack ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 Chris Hines - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/golang/snappy ----------------------------------------------------------------------- - -Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/google/gopacket ----------------------------------------------------------------------- - -Copyright (c) 2012 Google, Inc. All rights reserved. -Copyright (c) 2009-2011 Andreas Krennmair. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Andreas Krennmair, Google, nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/gopherjs/gopherjs ----------------------------------------------------------------------- - -Copyright (c) 2013 Richard Musiol. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/howeyc/gopass ----------------------------------------------------------------------- - -Copyright (c) 2012 Chris Howey - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/jessevdk/go-flags ----------------------------------------------------------------------- - -Copyright (c) 2012 Jesse van den Kieboom. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following disclaimer - in the documentation and/or other materials provided with the - distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/jtolds/gls ----------------------------------------------------------------------- - -Copyright (c) 2013, Space Monkey, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mattn/go-runewidth ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2016 Yasuhiro Matsumoto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/mongodb/mongo-go-driver ----------------------------------------------------------------------- - - 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. - ----------------------------------------------------------------------- -License notice for github.com/nsf/termbox-go ----------------------------------------------------------------------- - -Copyright (C) 2012 termbox-go authors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/patrickmn/go-cache ----------------------------------------------------------------------- - -Copyright (c) 2012-2015 Patrick Mylund Nielsen and the go-cache contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions ----------------------------------------------------------------------- - -Copyright (c) 2015 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/go-render ----------------------------------------------------------------------- - -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglematchers ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/oglemock ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/ogletest ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/assertions/internal/reqtrace ----------------------------------------------------------------------- - - 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. - - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey ----------------------------------------------------------------------- - -Copyright (c) 2014 SmartyStreets, LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -NOTE: Various optional and subordinate components carry their own licensing -requirements and restrictions. Use of those components is subject to the terms -and conditions outlined the respective license of each component. - ----------------------------------------------------------------------- -License notice for github.com/smartystreets/goconvey/web/client/resources/fonts/Open_Sans ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/spacemonkeygo/spacelog ----------------------------------------------------------------------- - -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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/scram ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/xdg/stringprep ----------------------------------------------------------------------- - - - 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. - ----------------------------------------------------------------------- -License notice for github.com/youmark/pkcs8 ----------------------------------------------------------------------- - -The MIT License (MIT) - -Copyright (c) 2014 youmark - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - ----------------------------------------------------------------------- -License notice for golang.org/x/crypto ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/sync ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for golang.org/x/text ----------------------------------------------------------------------- - -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - ----------------------------------------------------------------------- -License notice for gopkg.in/tomb.v2 ----------------------------------------------------------------------- - -tomb - support for clean goroutine termination in Go. - -Copyright (c) 2010-2011 - Gustavo Niemeyer - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md index 02c13d74..b055fc41 100755 --- a/README.md +++ b/README.md @@ -29,6 +29,5 @@ for integration steps once available. ## Documentation - `docs/README.md` now consolidates the platform index and points to the updated high-level architecture. -- Module architecture dossiers live under `docs/ARCHITECTURE_*.md`; the most relevant here are `docs/ARCHITECTURE_CONCELIER.md` (service layout, merge engine, exports) and `docs/ARCHITECTURE_CLI.md` (command surface, AOT packaging, auth flows). Related services such as the Signer, Attestor, Authority, Scanner, UI, Excititor, Zastava, and DevOps pipeline each have their own dossier. -- Offline operation guidance moved to `docs/24_OFFLINE_KIT.md`, which details bundle composition, verification, and delta workflows. Concelier-specific connector operations stay in `docs/ops/concelier-certbund-operations.md` and companion runbooks under `docs/ops/`. - +- Module architecture dossiers now live under `docs/modules//`. The most relevant here are `docs/modules/concelier/ARCHITECTURE.md` (service layout, merge engine, exports) and `docs/modules/cli/ARCHITECTURE.md` (command surface, AOT packaging, auth flows). Related services such as the Signer, Attestor, Authority, Scanner, UI, Excititor, Zastava, and DevOps pipeline each have their own dossier in the same hierarchy. +- Offline operation guidance moved to `docs/24_OFFLINE_KIT.md`, which details bundle composition, verification, and delta workflows. Concelier-specific connector operations stay in `docs/modules/concelier/operations/connectors/*.md` with companion runbooks in `docs/modules/concelier/operations/`. diff --git a/deploy/README.md b/deploy/README.md index cf22949f..4d0b920d 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -1,10 +1,10 @@ -# Deployment Profiles - -This directory contains deterministic deployment bundles for the core Stella Ops stack. All manifests reference immutable image digests and map 1:1 to the release manifests stored under `deploy/releases/`. - -## Structure - -- `releases/` – canonical release manifests (edge, stable, airgap) used to source image digests. +# Deployment Profiles + +This directory contains deterministic deployment bundles for the core Stella Ops stack. All manifests reference immutable image digests and map 1:1 to the release manifests stored under `deploy/releases/`. + +## Structure + +- `releases/` – canonical release manifests (edge, stable, airgap) used to source image digests. - `compose/` – Docker Compose bundles for dev/stage/airgap targets plus `.env` seed files. - `compose/docker-compose.mirror.yaml` – managed mirror bundle for `*.stella-ops.org` with gateway cache and multi-tenant auth. - `compose/docker-compose.telemetry.yaml` – optional OpenTelemetry collector overlay (mutual TLS, OTLP pipelines). @@ -12,11 +12,11 @@ This directory contains deterministic deployment bundles for the core Stella Ops - `helm/stellaops/` – multi-profile Helm chart with values files for dev/stage/airgap. - `telemetry/` – shared OpenTelemetry collector configuration and certificate artefacts (generated via tooling). - `tools/validate-profiles.sh` – helper that runs `docker compose config` and `helm lint/template` for every profile. - -## Workflow - -1. Update or add a release manifest under `releases/` with the new digests. -2. Mirror the digests into the Compose and Helm profiles that correspond to that channel. + +## Workflow + +1. Update or add a release manifest under `releases/` with the new digests. +2. Mirror the digests into the Compose and Helm profiles that correspond to that channel. 3. Run `deploy/tools/validate-profiles.sh` (requires Docker CLI and Helm) to ensure the bundles lint and template cleanly. 4. If telemetry ingest is required for the release, generate development certificates using `./ops/devops/telemetry/generate_dev_tls.sh` and run the collector smoke test with @@ -31,7 +31,7 @@ Maintaining the digest linkage keeps offline/air-gapped installs reproducible an - `ops/devops/telemetry/generate_dev_tls.sh` – produces local CA/server/client certificates for Compose-based collector testing. - `ops/devops/telemetry/smoke_otel_collector.py` – sends OTLP traffic and asserts the collector accepted traces, metrics, and logs. - `ops/devops/telemetry/package_offline_bundle.py` – packages telemetry assets (config/Helm/Compose) into a signed tarball for air-gapped installs. -- `docs/ops/deployment-upgrade-runbook.md` – end-to-end instructions for upgrade, rollback, and channel promotion workflows (Helm + Compose). +- `docs/modules/devops/runbooks/deployment-upgrade.md` – end-to-end instructions for upgrade, rollback, and channel promotion workflows (Helm + Compose). ## CI smoke checks diff --git a/deploy/telemetry/storage/README.md b/deploy/telemetry/storage/README.md index b3e5899c..1fab323f 100644 --- a/deploy/telemetry/storage/README.md +++ b/deploy/telemetry/storage/README.md @@ -1,33 +1,33 @@ -# Telemetry Storage Stack - -Configuration snippets for the default StellaOps observability backends used in -staging and production environments. The stack comprises: - -- **Prometheus** for metrics (scraping the collector's Prometheus exporter) -- **Tempo** for traces (OTLP ingest via mTLS) -- **Loki** for logs (HTTP ingest with tenant isolation) - -## Files - -| Path | Description | -| ---- | ----------- | -| `prometheus.yaml` | Scrape configuration for the collector (mTLS + bearer token placeholder). | -| `tempo.yaml` | Tempo configuration with multitenancy enabled and local storage paths. | -| `loki.yaml` | Loki configuration enabling per-tenant overrides and boltdb-shipper storage. | -| `tenants/tempo-overrides.yaml` | Example tenant overrides for Tempo (retention, limits). | -| `tenants/loki-overrides.yaml` | Example tenant overrides for Loki (rate limits, retention). | -| `auth/` | Placeholder directory for Prometheus bearer token files (e.g., `token`). | - -These configurations are referenced by the Docker Compose overlay -(`deploy/compose/docker-compose.telemetry-storage.yaml`) and the staging rollout documented in -`docs/ops/telemetry-storage.md`. Adjust paths, credentials, and overrides before running in -connected environments. Place the Prometheus bearer token in `auth/token` when using the -Compose overlay (the directory contains a `.gitkeep` placeholder and is gitignored by default). - -## Security - -- Both Tempo and Loki require mutual TLS. -- Prometheus uses mTLS plus a bearer token that should be minted by Authority. -- Update the overrides files to enforce per-tenant retention/ingestion limits. - -For comprehensive deployment steps see `docs/ops/telemetry-storage.md`. +# Telemetry Storage Stack + +Configuration snippets for the default StellaOps observability backends used in +staging and production environments. The stack comprises: + +- **Prometheus** for metrics (scraping the collector's Prometheus exporter) +- **Tempo** for traces (OTLP ingest via mTLS) +- **Loki** for logs (HTTP ingest with tenant isolation) + +## Files + +| Path | Description | +| ---- | ----------- | +| `prometheus.yaml` | Scrape configuration for the collector (mTLS + bearer token placeholder). | +| `tempo.yaml` | Tempo configuration with multitenancy enabled and local storage paths. | +| `loki.yaml` | Loki configuration enabling per-tenant overrides and boltdb-shipper storage. | +| `tenants/tempo-overrides.yaml` | Example tenant overrides for Tempo (retention, limits). | +| `tenants/loki-overrides.yaml` | Example tenant overrides for Loki (rate limits, retention). | +| `auth/` | Placeholder directory for Prometheus bearer token files (e.g., `token`). | + +These configurations are referenced by the Docker Compose overlay +(`deploy/compose/docker-compose.telemetry-storage.yaml`) and the staging rollout documented in +`docs/modules/telemetry/operations/storage.md`. Adjust paths, credentials, and overrides before running in +connected environments. Place the Prometheus bearer token in `auth/token` when using the +Compose overlay (the directory contains a `.gitkeep` placeholder and is gitignored by default). + +## Security + +- Both Tempo and Loki require mutual TLS. +- Prometheus uses mTLS plus a bearer token that should be minted by Authority. +- Update the overrides files to enforce per-tenant retention/ingestion limits. + +For comprehensive deployment steps see `docs/modules/telemetry/operations/storage.md`. diff --git a/docs/09_API_CLI_REFERENCE.md b/docs/09_API_CLI_REFERENCE.md index bc0efe46..de49a92d 100755 --- a/docs/09_API_CLI_REFERENCE.md +++ b/docs/09_API_CLI_REFERENCE.md @@ -616,7 +616,7 @@ See `docs/dev/32_AUTH_CLIENT_GUIDE.md` for recommended profiles (online vs. air- |---------|---------|-----------------------|-------| | `stellaops-cli scanner download` | Fetch and install scanner container | `--channel ` (default `stable`)
`--output `
`--overwrite`
`--no-install` | Saves artefact under `ScannerCacheDirectory`, verifies digest/signature, and executes `docker load` unless `--no-install` is supplied. | | `stellaops-cli scan run` | Execute scanner container against a directory (auto-upload) | `--target ` (required)
`--runner ` (default from config)
`--entry `
`[scanner-args...]` | Runs the scanner, writes results into `ResultsDirectory`, emits a structured `scan-run-*.json` metadata file, and automatically uploads the artefact when the exit code is `0`. | -| `stellaops-cli scan upload` | Re-upload existing scan artefact | `--file ` | Useful for retries when automatic upload fails or when operating offline. | +| `stellaops-cli scan upload` | Re-upload existing scan artefact | `--file ` | Useful for retries when automatic upload fails or when operating offline. | | `stellaops-cli db fetch` | Trigger connector jobs | `--source ` (e.g. `redhat`, `osv`)
`--stage ` (default `fetch`)
`--mode ` | Translates to `POST /jobs/source:{source}:{stage}` with `trigger=cli` | | `stellaops-cli db merge` | Run canonical merge reconcile | — | Calls `POST /jobs/merge:reconcile`; exit code `0` on acceptance, `1` on failures/conflicts | | `stellaops-cli db export` | Kick JSON / Trivy exports | `--format ` (default `json`)
`--delta`
`--publish-full/--publish-delta`
`--bundle-full/--bundle-delta` | Sets `{ delta = true }` parameter when requested and can override ORAS/bundle toggles per run | @@ -629,7 +629,9 @@ See `docs/dev/32_AUTH_CLIENT_GUIDE.md` for recommended profiles (online vs. air- | `stellaops-cli sources ingest --dry-run` | Dry-run guard validation for individual payloads | `--source `
`--input `
`--tenant `
`--format table\|json`
`--output ` | Normalises gzip/base64 payloads, invokes `api/aoc/ingest/dry-run`, and maps guard failures to deterministic `ERR_AOC_00x` exit codes. | | `stellaops-cli aoc verify` | Replay AOC guardrails over stored documents | `--since `
`--limit `
`--sources `
`--codes `
`--format table\|json`
`--export ` | Summarises checked counts/violations, supports JSON evidence exports, and returns `0`, `11…17`, `18`, `70`, or `71` depending on guard outcomes. | | `stellaops-cli config show` | Display resolved configuration | — | Masks secret values; helpful for air‑gapped installs | -| `stellaops-cli runtime policy test` | Ask Scanner.WebService for runtime verdicts (Webhook parity) | `--image/-i ` (repeatable, comma/space lists supported)
`--file/-f `
`--namespace/--ns `
`--label/-l key=value` (repeatable)
`--json` | Posts to `POST /api/v1/scanner/policy/runtime`, deduplicates image digests, and prints TTL/policy revision plus per-image columns for signed state, SBOM referrers, quieted-by metadata, confidence, Rekor attestation (uuid + verified flag), and recently observed build IDs (shortened for readability). Accepts newline/whitespace-delimited stdin when piped; `--json` emits the raw response without additional logging. | +| `stellaops-cli runtime policy test` | Ask Scanner.WebService for runtime verdicts (Webhook parity) | `--image/-i ` (repeatable, comma/space lists supported)
`--file/-f `
`--namespace/--ns `
`--label/-l key=value` (repeatable)
`--json` | Posts to `POST /api/v1/scanner/policy/runtime`, deduplicates image digests, and prints TTL/policy revision plus per-image columns for signed state, SBOM referrers, quieted-by metadata, confidence, Rekor attestation (uuid + verified flag), and recently observed build IDs (shortened for readability). Accepts newline/whitespace-delimited stdin when piped; `--json` emits the raw response without additional logging. | + +> Need to debug how the scanner resolves entry points? See the [entry-point documentation index](modules/scanner/operations/entrypoint.md), which links to static/dynamic reducers, ShellFlow, and runtime-specific guides. #### Example: Pivot from runtime verdicts to debug symbols diff --git a/docs/10_CONCELIER_CLI_QUICKSTART.md b/docs/10_CONCELIER_CLI_QUICKSTART.md index c4fdc7b6..9f3d1d18 100644 --- a/docs/10_CONCELIER_CLI_QUICKSTART.md +++ b/docs/10_CONCELIER_CLI_QUICKSTART.md @@ -351,4 +351,4 @@ a problem document. - **Rollout checklist.** 1. Stage the integration with fallback enabled (`allowAnonymousFallback=true`) and confirm CLI/token issuance using `stella auth status`. 2. Follow the rehearsal pattern (`allowAnonymousFallback=false`) while monitoring `Concelier.Authorization.Audit` and `web.jobs.triggered`/`web.jobs.trigger.failed` metrics. - 3. Lock in enforcement, review the audit runbook (`docs/ops/concelier-authority-audit-runbook.md`), and document the bypass CIDR approvals in your change log. + 3. Lock in enforcement, review the audit runbook (`docs/modules/concelier/operations/authority-audit-runbook.md`), and document the bypass CIDR approvals in your change log. diff --git a/docs/11_DATA_SCHEMAS.md b/docs/11_DATA_SCHEMAS.md index 6a5c7413..d606689e 100755 --- a/docs/11_DATA_SCHEMAS.md +++ b/docs/11_DATA_SCHEMAS.md @@ -452,14 +452,14 @@ Planned for Q1‑2026 (kept here for early plug‑in authors). ## 6 Notify Foundations (Rule · Channel · Event) -*Sprint 15 target* – canonically describe the Notify data shapes that UI, workers, and storage consume. JSON Schemas live under `docs/notify/schemas/` and deterministic fixtures under `docs/notify/samples/`. +*Sprint 15 target* – canonically describe the Notify data shapes that UI, workers, and storage consume. JSON Schemas live under `docs/modules/notify/resources/schemas/` and deterministic fixtures under `docs/modules/notify/resources/samples/`. | Artifact | Schema | Sample | |----------|--------|--------| -| **Rule** (catalogued routing logic) | `docs/notify/schemas/notify-rule@1.json` | `docs/notify/samples/notify-rule@1.sample.json` | -| **Channel** (delivery endpoint definition) | `docs/notify/schemas/notify-channel@1.json` | `docs/notify/samples/notify-channel@1.sample.json` | -| **Template** (rendering payload) | `docs/notify/schemas/notify-template@1.json` | `docs/notify/samples/notify-template@1.sample.json` | -| **Event envelope** (Notify ingest surface) | `docs/notify/schemas/notify-event@1.json` | `docs/notify/samples/notify-event@1.sample.json` | +| **Rule** (catalogued routing logic) | `docs/modules/notify/resources/schemas/notify-rule@1.json` | `docs/modules/notify/resources/samples/notify-rule@1.sample.json` | +| **Channel** (delivery endpoint definition) | `docs/modules/notify/resources/schemas/notify-channel@1.json` | `docs/modules/notify/resources/samples/notify-channel@1.sample.json` | +| **Template** (rendering payload) | `docs/modules/notify/resources/schemas/notify-template@1.json` | `docs/modules/notify/resources/samples/notify-template@1.sample.json` | +| **Event envelope** (Notify ingest surface) | `docs/modules/notify/resources/schemas/notify-event@1.json` | `docs/modules/notify/resources/samples/notify-event@1.sample.json` | ### 6.1 Rule highlights (`notify-rule@1`) @@ -498,12 +498,12 @@ Planned for Q1‑2026 (kept here for early plug‑in authors). ```bash # Validate Notify schemas and samples (matches Docs CI) -for schema in docs/notify/schemas/*.json; do +for schema in docs/modules/notify/resources/schemas/*.json; do npx ajv compile -c ajv-formats -s "$schema" done -for sample in docs/notify/samples/*.sample.json; do - schema="docs/notify/schemas/$(basename "${sample%.sample.json}").json" +for sample in docs/modules/notify/resources/samples/*.sample.json; do + schema="docs/modules/notify/resources/schemas/$(basename "${sample%.sample.json}").json" npx ajv validate -c ajv-formats -s "$schema" -d "$sample" done ``` diff --git a/docs/12_PERFORMANCE_WORKBOOK.md b/docs/12_PERFORMANCE_WORKBOOK.md index 1444ed63..4c96b766 100755 --- a/docs/12_PERFORMANCE_WORKBOOK.md +++ b/docs/12_PERFORMANCE_WORKBOOK.md @@ -145,7 +145,7 @@ P99 = 48 ms. Meets 50 ms gate. ![Perf trend spark‑line placeholder](perf‑trend.svg) -> **Grafana/Alerting** – Import `docs/ops/scanner-analyzers-grafana-dashboard.json` and point it at the Prometheus datasource storing `scanner_analyzer_bench_*` metrics. Configure an alert on `scanner_analyzer_bench_regression_ratio` ≥ 1.20 (default limit); the bundled Stat panel surfaces breached scenarios (non-zero values). On-call runbook: `docs/ops/scanner-analyzers-operations.md`. +> **Grafana/Alerting** – Import `docs/modules/scanner/operations/analyzers-grafana-dashboard.json` and point it at the Prometheus datasource storing `scanner_analyzer_bench_*` metrics. Configure an alert on `scanner_analyzer_bench_regression_ratio` ≥ 1.20 (default limit); the bundled Stat panel surfaces breached scenarios (non-zero values). On-call runbook: `docs/modules/scanner/operations/analyzers.md`. _Plot generated weekly by `scripts/update‑trend.py`; shows last 12 weeks P95 per phase._ diff --git a/docs/13_RELEASE_ENGINEERING_PLAYBOOK.md b/docs/13_RELEASE_ENGINEERING_PLAYBOOK.md index 2221c4dc..1da8f496 100755 --- a/docs/13_RELEASE_ENGINEERING_PLAYBOOK.md +++ b/docs/13_RELEASE_ENGINEERING_PLAYBOOK.md @@ -1,62 +1,62 @@ -# 13 · Release Engineering Playbook — Stella Ops - - -A concise, automation‑first guide describing **how source code on `main` becomes a verifiably signed, air‑gap‑friendly release**. -It is opinionated for offline use‑cases and supply‑chain security (SLSA ≥ level 2 today, aiming for level 3). - ---- - -## 0 Release Philosophy - -* **Fast but fearless** – every commit on `main` must be releasable; broken builds break the build, not the team. -* **Reproducible** – anyone can rebuild byte‑identical artefacts with a single `make release` offline. -* **Secure by default** – every artefact ships with a SBOM, Cosign signature and (future) Rekor log entry. -* **Offline‑first** – all dependencies are vendored or mirrored into the internal registry; no Internet required at runtime. - ---- - -## 1 Versioning & Branching - -| Branch | Purpose | Auto‑publish? | -| ------------- | ------------------------------ | --------------------------------------- | -| `main` | Always‑green development trunk | `nightly-*` images | -| `release/X.Y` | Stabilise a minor line | `stella:X.Y-rcN` | -| Tags | `X.Y.Z` = SemVer | `stella:X.Y.Z`, OUK tarball, Helm chart | - -* **SemVer** – MAJOR for breaking API/CLI changes, MINOR for features, PATCH for fixes. -* Release tags are **signed** (`git tag -s`) with the Stella Ops GPG key (`0x90C4…`). - ---- - -## 2 CI/CD Overview (GitLab CI + GitLab Runner) - -```mermaid -graph LR - A[push / MR] --> Lint - Lint --> Unit - Unit --> Build - Build --> Test-Container - Test-Container --> SBOM - SBOM --> Sign - Sign --> Publish - Publish --> E2E - Publish --> Notify -``` - -### Pipeline Stages - -| Stage | Key tasks | -| ------------------ | ------------------------------------------------------------------------------------------------ | -| **Lint** | ESLint, golangci‑lint, hadolint, markdown‑lint. | -| **Unit** | `dotnet test`, `go test`, Jest UI tests. | -| **Quota unit‑tests 🏷** | Validate QuotaService logic: reset at UTC, 5 s vs 60 s waits, header correctness. | -| **Build** | Multi‑arch container build (`linux/amd64`, `linux/arm64`) using **BuildKit** + `--provenance` 📌. | -| **Test‑Container** | Spin up compose file, run smoke APIs. | -| **SBOM** 📌 | Invoke **StellaOps.SBOMBuilder** to generate SPDX JSON + attach `.sbom` label to image. | -| **Sign** | Sign image with **Cosign** (`cosign sign --key cosign.key`). | -| **Publish** | Push to `registry.git.stella-ops.org`. | -| **E2E** | Kind‑based Kubernetes test incl. Zastava DaemonSet; verify sub‑5 s scan SLA. | -| **Notify** | Report to Mattermost & GitLab Slack app. | +# 13 · Release Engineering Playbook — Stella Ops + + +A concise, automation‑first guide describing **how source code on `main` becomes a verifiably signed, air‑gap‑friendly release**. +It is opinionated for offline use‑cases and supply‑chain security (SLSA ≥ level 2 today, aiming for level 3). + +--- + +## 0 Release Philosophy + +* **Fast but fearless** – every commit on `main` must be releasable; broken builds break the build, not the team. +* **Reproducible** – anyone can rebuild byte‑identical artefacts with a single `make release` offline. +* **Secure by default** – every artefact ships with a SBOM, Cosign signature and (future) Rekor log entry. +* **Offline‑first** – all dependencies are vendored or mirrored into the internal registry; no Internet required at runtime. + +--- + +## 1 Versioning & Branching + +| Branch | Purpose | Auto‑publish? | +| ------------- | ------------------------------ | --------------------------------------- | +| `main` | Always‑green development trunk | `nightly-*` images | +| `release/X.Y` | Stabilise a minor line | `stella:X.Y-rcN` | +| Tags | `X.Y.Z` = SemVer | `stella:X.Y.Z`, OUK tarball, Helm chart | + +* **SemVer** – MAJOR for breaking API/CLI changes, MINOR for features, PATCH for fixes. +* Release tags are **signed** (`git tag -s`) with the Stella Ops GPG key (`0x90C4…`). + +--- + +## 2 CI/CD Overview (GitLab CI + GitLab Runner) + +```mermaid +graph LR + A[push / MR] --> Lint + Lint --> Unit + Unit --> Build + Build --> Test-Container + Test-Container --> SBOM + SBOM --> Sign + Sign --> Publish + Publish --> E2E + Publish --> Notify +``` + +### Pipeline Stages + +| Stage | Key tasks | +| ------------------ | ------------------------------------------------------------------------------------------------ | +| **Lint** | ESLint, golangci‑lint, hadolint, markdown‑lint. | +| **Unit** | `dotnet test`, `go test`, Jest UI tests. | +| **Quota unit‑tests 🏷** | Validate QuotaService logic: reset at UTC, 5 s vs 60 s waits, header correctness. | +| **Build** | Multi‑arch container build (`linux/amd64`, `linux/arm64`) using **BuildKit** + `--provenance` 📌. | +| **Test‑Container** | Spin up compose file, run smoke APIs. | +| **SBOM** 📌 | Invoke **StellaOps.SBOMBuilder** to generate SPDX JSON + attach `.sbom` label to image. | +| **Sign** | Sign image with **Cosign** (`cosign sign --key cosign.key`). | +| **Publish** | Push to `registry.git.stella-ops.org`. | +| **E2E** | Kind‑based Kubernetes test incl. Zastava DaemonSet; verify sub‑5 s scan SLA. | +| **Notify** | Report to Mattermost & GitLab Slack app. | | **OfflineToken** | Call `JwtIssuer.Generate(exp=30d)` → store `client.jwt` artefact → attach to OUK build context | *All stages run in parallel where possible; max wall‑time < 15 min.* @@ -70,63 +70,63 @@ The `build-test-deploy` workflow also runs regressions fail fast during every CI pass. --- - -## 3 Container Image Strategy - -| Image | Registry Tag | Contents | -| ------------------------------ | --------------------------- | ---------------------------------------------------------------------- | -| **backend** | `stella/backend:{ver}` | ASP.NET API, plugin loader. | -| **ui** | `stella/ui:{ver}` | Pre‑built Angular SPA. | -| **runner-trivy** | `stella/runner-trivy:{ver}` | Trivy CLI + SPDX/CycloneDX 🛠. | -| **runner-grype** | `stella/runner-grype:{ver}` | Optional plug‑in scanner. | -| **🏷️ StellaOps.Registry** 📌 | `stella/registry:{ver}` | Scratch image embedding Docker Registry v2 + Cosign policy controller. | -| **🏷️ StellaOps.MutePolicies** 📌 | `stella/policies:{ver}` | Sidecar serving policy bundles. | -| **🏷️ StellaOps.Attestor** 📌 | `stella/attestor:{ver}` | SLSA provenance & Rekor signer (future). | - -*Images are **`--label org.opencontainers.image.source=git.stella-ops.ru`** and include SBOMs generated at build time.* - ---- - -## 4 📌 Offline Update Kit (OUK) Build & Distribution - -**Purpose** – deliver updated CVE feeds & Trivy DB to air‑gapped clusters. - -### 4.1 CLI Tool - -*Go binary `ouk` lives in `tools/ouk/`.* - -```sh -ouk fetch \ - --nvd --osv \ - --trivy-db --date $(date -I) \ - --output ouk-$(date +%Y%m%d).tar.gz \ - --sign cosign.key -``` - + +## 3 Container Image Strategy + +| Image | Registry Tag | Contents | +| ------------------------------ | --------------------------- | ---------------------------------------------------------------------- | +| **backend** | `stella/backend:{ver}` | ASP.NET API, plugin loader. | +| **ui** | `stella/ui:{ver}` | Pre‑built Angular SPA. | +| **runner-trivy** | `stella/runner-trivy:{ver}` | Trivy CLI + SPDX/CycloneDX 🛠. | +| **runner-grype** | `stella/runner-grype:{ver}` | Optional plug‑in scanner. | +| **🏷️ StellaOps.Registry** 📌 | `stella/registry:{ver}` | Scratch image embedding Docker Registry v2 + Cosign policy controller. | +| **🏷️ StellaOps.MutePolicies** 📌 | `stella/policies:{ver}` | Sidecar serving policy bundles. | +| **🏷️ StellaOps.Attestor** 📌 | `stella/attestor:{ver}` | SLSA provenance & Rekor signer (future). | + +*Images are **`--label org.opencontainers.image.source=git.stella-ops.ru`** and include SBOMs generated at build time.* + +--- + +## 4 📌 Offline Update Kit (OUK) Build & Distribution + +**Purpose** – deliver updated CVE feeds & Trivy DB to air‑gapped clusters. + +### 4.1 CLI Tool + +*Go binary `ouk` lives in `src/Tools/ouk/`.* + +```sh +ouk fetch \ + --nvd --osv \ + --trivy-db --date $(date -I) \ + --output ouk-$(date +%Y%m%d).tar.gz \ + --sign cosign.key +``` + ### 4.2 Pipeline Hook * Runs on **first Friday** each month (cron). * Generates tarball, signs it, uploads to **GitLab Release asset**. * SHA‑256 + signature published alongside. * Release job must emit `out/release/debug/` with `debug-manifest.json` and `.sha256` so `ops/offline-kit/mirror_debug_store.py` can mirror symbols into the Offline Kit (see `DEVOPS-REL-17-004`). - -### 4.3 Activation Flow (runtime) - -1. Admin uploads `.tar.gz` via **UI → Settings → Offline Updates (OUK)**. -2. Backend verifies Cosign signature & digest. -3. Files extracted into `var/lib/stella/db`. -4. Redis caches invalidated; Dashboard “Feed Age” ticks green. -5. Audit event `ouk_update` stored. - -### 4.4 Token Detail - -client.jwt placed under /root/ inside the tarball. -CI job fails if token expiry < 29 days (guard against stale caches). - ---- - -## 5 Artifact Signing & Transparency - + +### 4.3 Activation Flow (runtime) + +1. Admin uploads `.tar.gz` via **UI → Settings → Offline Updates (OUK)**. +2. Backend verifies Cosign signature & digest. +3. Files extracted into `var/lib/stella/db`. +4. Redis caches invalidated; Dashboard “Feed Age” ticks green. +5. Audit event `ouk_update` stored. + +### 4.4 Token Detail + +client.jwt placed under /root/ inside the tarball. +CI job fails if token expiry < 29 days (guard against stale caches). + +--- + +## 5 Artifact Signing & Transparency + | Artefact | Signer | Tool/Notes | | ------------ | --------------- | ---------------------------------- | | Git tags | GPG (`0x90C4…`) | `git tag -s` | @@ -134,18 +134,18 @@ CI job fails if token expiry < 29 days (guard against stale caches). | Helm Charts | prov file | `helm package --sign` | | OUK tarballs | Cosign | `cosign sign-blob` | | Debug store | — | `debug/debug-manifest.json` hashed | - -**Rekor** integration is **TODO** – once the internal Rekor mirror is online (`StellaOpsAttestor`) a post‑publish job will submit transparency log entries. - ---- - -## 6 Release Checklist - -1. CI pipeline green. -2. Bump `VERSION` file. -3. Tag `git tag -s X.Y.Z -m "Release X.Y.Z"` & push. -4. GitLab CI auto‑publishes images & charts. -5. Draft GitLab **Release Notes** using `tools/release-notes-gen`. + +**Rekor** integration is **TODO** – once the internal Rekor mirror is online (`StellaOpsAttestor`) a post‑publish job will submit transparency log entries. + +--- + +## 6 Release Checklist + +1. CI pipeline green. +2. Bump `VERSION` file. +3. Tag `git tag -s X.Y.Z -m "Release X.Y.Z"` & push. +4. GitLab CI auto‑publishes images & charts. +5. Draft GitLab **Release Notes** using `src/Tools/release-notes-gen`. 6. Verify SBOM attachment with `stella sbom verify stella/backend:X.Y.Z`. 7. Run the release verifier locally if CI isn’t available (mirrors the workflow step): `python ops/devops/release/test_verify_release.py` @@ -160,71 +160,71 @@ CI job fails if token expiry < 29 days (guard against stale caches). Validate that the hash from `readelf` matches the `.build-id//.debug` path created by the script. 9. Smoke-test OUK tarball in offline lab. 10. Announce in `#stella-release` Mattermost channel. - ---- - -## 7 Hot‑fix Procedure - -* Branch from latest tag → `hotfix/X.Y.Z+1-hf1`. -* Apply minimal patch, add regression test. -* CI pipeline (with reduced stages) must pass. -* Tag `X.Y.Z+1`. -* Publish only container + Helm chart; OUK not rebuilt. -* Cherry‑pick back to `main`. - ---- - -## 8 Deprecation & End‑of‑Life Policy - -| Feature | Deprecation notice | Removal earliest | -| ------------------------ | ------------------ | ---------------- | -| Legacy CSV policy import | 2025‑10‑01 | 2026‑04‑01 | -| Docker v1 Registry auth | 2025‑12‑01 | 2026‑06‑01 | -| In‑image Trivy DB | 2025‑12‑15 | 2026‑03‑15 | - -*At least 6 months notice; removal requires major version bump.* - ---- - -## 9 📌 Non‑Commercial Usage Rules (English canonical) - -1. **Free for internal security assessments** (company or personal). -2. **SaaS resale / re‑hosting prohibited** without prior written consent (AGPL §13). -3. If you distribute a fork with UI or backend modifications **you must**: - * Publish the complete modified source code. - * Retain the original Stella Ops attribution in UI footer and CLI `--version`. -4. All third‑party dependencies remain under their respective licences (MIT, Apache‑2.0, ISC, BSD). -5. Deployments in state‑regulated or classified environments must obey**applicable local regulations** governing cryptography and software distribution. - ---- - -## 10 Best Practices Snapshot 📌 - -* **SBOM‑per‑image** → attach at build time; store as OCI artifact for supply‑chain introspection. -* **Provenance flag** (`--provenance=true`) in BuildKit fulfils SLSA 2 requirement. -* Use **multi‑arch, reproducible builds** (`SOURCE_DATE_EPOCH` pins timestamps). -* All pipelines enforce **Signed‑off‑by (DCO)**; CI fails if trailer missing. -* `cosign policy` ensures only images signed by the project key run in production. - ---- - -## 11 Contributing to Release Engineering - -* Fork & create MR to `infra/release-*`. -* All infra changes require green **`integration-e2e-offline`** job. -* Discuss larger infra migrations in `#sig-release` Mattermost; decisions recorded in `ADR/` folder. - ---- - -## 12 Change Log (high‑level) - -| Version | Date | Note | -| ------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -| v2.1 | 2025‑07‑15 | Added OUK build/publish pipeline, internal registry image (`StellaOps.Registry`), non‑commercial usage rules extraction, SBOM stage, BuildKit provenance. | -| v2.0 | 2025‑07‑12 | Initial open‑sourcing of Release Engineering guide. | -| v1.1 | 2025‑07‑09 | Fixed inner fencing; added retention policy | -| v1.0 | 2025‑07‑09 | Initial playbook | - ---- - -*(End of Release Engineering Playbook v1.1)* + +--- + +## 7 Hot‑fix Procedure + +* Branch from latest tag → `hotfix/X.Y.Z+1-hf1`. +* Apply minimal patch, add regression test. +* CI pipeline (with reduced stages) must pass. +* Tag `X.Y.Z+1`. +* Publish only container + Helm chart; OUK not rebuilt. +* Cherry‑pick back to `main`. + +--- + +## 8 Deprecation & End‑of‑Life Policy + +| Feature | Deprecation notice | Removal earliest | +| ------------------------ | ------------------ | ---------------- | +| Legacy CSV policy import | 2025‑10‑01 | 2026‑04‑01 | +| Docker v1 Registry auth | 2025‑12‑01 | 2026‑06‑01 | +| In‑image Trivy DB | 2025‑12‑15 | 2026‑03‑15 | + +*At least 6 months notice; removal requires major version bump.* + +--- + +## 9 📌 Non‑Commercial Usage Rules (English canonical) + +1. **Free for internal security assessments** (company or personal). +2. **SaaS resale / re‑hosting prohibited** without prior written consent (AGPL §13). +3. If you distribute a fork with UI or backend modifications **you must**: + * Publish the complete modified source code. + * Retain the original Stella Ops attribution in UI footer and CLI `--version`. +4. All third‑party dependencies remain under their respective licences (MIT, Apache‑2.0, ISC, BSD). +5. Deployments in state‑regulated or classified environments must obey**applicable local regulations** governing cryptography and software distribution. + +--- + +## 10 Best Practices Snapshot 📌 + +* **SBOM‑per‑image** → attach at build time; store as OCI artifact for supply‑chain introspection. +* **Provenance flag** (`--provenance=true`) in BuildKit fulfils SLSA 2 requirement. +* Use **multi‑arch, reproducible builds** (`SOURCE_DATE_EPOCH` pins timestamps). +* All pipelines enforce **Signed‑off‑by (DCO)**; CI fails if trailer missing. +* `cosign policy` ensures only images signed by the project key run in production. + +--- + +## 11 Contributing to Release Engineering + +* Fork & create MR to `infra/release-*`. +* All infra changes require green **`integration-e2e-offline`** job. +* Discuss larger infra migrations in `#sig-release` Mattermost; decisions recorded in `ADR/` folder. + +--- + +## 12 Change Log (high‑level) + +| Version | Date | Note | +| ------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| v2.1 | 2025‑07‑15 | Added OUK build/publish pipeline, internal registry image (`StellaOps.Registry`), non‑commercial usage rules extraction, SBOM stage, BuildKit provenance. | +| v2.0 | 2025‑07‑12 | Initial open‑sourcing of Release Engineering guide. | +| v1.1 | 2025‑07‑09 | Fixed inner fencing; added retention policy | +| v1.0 | 2025‑07‑09 | Initial playbook | + +--- + +*(End of Release Engineering Playbook v1.1)* diff --git a/docs/17_SECURITY_HARDENING_GUIDE.md b/docs/17_SECURITY_HARDENING_GUIDE.md index 355f4c0d..6eae1241 100755 --- a/docs/17_SECURITY_HARDENING_GUIDE.md +++ b/docs/17_SECURITY_HARDENING_GUIDE.md @@ -1,145 +1,145 @@ -#  17 · Security Hardening Guide — **Stella Ops** -*(v2.0 — 12 Jul 2025)* - -> **Audience** — Site‑reliability and platform teams deploying **the open‑source Core** in production or restricted networks. ---- - -##  0 Table of Contents - -1. Threat model (summary) -2. Host‑OS baseline -3. Container & runtime hardening -4. Network‑plane guidance -5. Secrets & key management -6. Image, SBOM & plug‑in supply‑chain controls -7. Logging, monitoring & audit -8. Update & patch strategy -9. Incident‑response workflow -10. Pen‑testing & continuous assurance -11. Contacts & vulnerability disclosure -12. Change log - ---- - -##  1 Threat model (summary) - -| Asset | Threats | Mitigations | -| -------------------- | --------------------- | ---------------------------------------------------------------------- | -| SBOMs & scan results | Disclosure, tamper | TLS‑in‑transit, read‑only Redis volume, RBAC, Cosign‑verified plug‑ins | -| Backend container | RCE, code‑injection | Distroless image, non‑root UID, read‑only FS, seccomp + `CAP_DROP:ALL` | -| Update artefacts | Supply‑chain attack | Cosign‑signed images & SBOMs, enforced by admission controller | -| Admin credentials | Phishing, brute force | OAuth 2.0 with 12‑h token TTL, optional mTLS | - ---- - -##  2 Host‑OS baseline checklist - -| Item | Recommended setting | -| ------------- | --------------------------------------------------------- | -| OS | Ubuntu 22.04 LTS (kernel ≥ 5.15) or Alma 9 | -| Patches | `unattended‑upgrades` or vendor‑equivalent enabled | -| Filesystem | `noexec,nosuid` on `/tmp`, `/var/tmp` | -| Docker Engine | v24.*, API socket root‑owned (`0660`) | -| Auditd | Watch `/etc/docker`, `/usr/bin/docker*` and Compose files | -| Time sync | `chrony` or `systemd‑timesyncd` | - ---- - -##  3 Container & runtime hardening - -###  3.1 Docker Compose reference (`compose-core.yml`) - -```yaml -services: - backend: - image: registry.stella-ops.org/stella-ops/stella-ops: - user: "101:101" # non‑root - read_only: true - security_opt: - - "no-new-privileges:true" - - "seccomp:./seccomp-backend.json" - cap_drop: [ALL] - tmpfs: - - /tmp:size=64m,exec,nosymlink - environment: - - ASPNETCORE_URLS=https://+:8080 - - TLSPROVIDER=OpenSslGost - depends_on: [redis] - networks: [core-net] - healthcheck: - test: ["CMD", "wget", "-qO-", "https://localhost:8080/health"] - interval: 30s - timeout: 5s - retries: 5 - - redis: - image: redis:7.2-alpine - command: ["redis-server", "--requirepass", "${REDIS_PASS}", "--rename-command", "FLUSHALL", ""] - user: "redis" - read_only: true - cap_drop: [ALL] - tmpfs: - - /data - networks: [core-net] - -networks: - core-net: - driver: bridge -``` - -No dedicated “Redis” or “Mongo” sub‑nets are declared; the single bridge network suffices for the default stack. - -###  3.2 Kubernetes deployment highlights - -Use a separate NetworkPolicy that only allows egress from backend to Redis :6379. -securityContext: runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation: false, drop all capabilities. -PodDisruptionBudget of minAvailable: 1. -Optionally add CosignVerified=true label enforced by an admission controller (e.g. Kyverno or Connaisseur). - -##  4 Network‑plane guidance - -| Plane | Recommendation | -| ------------------ | -------------------------------------------------------------------------- | -| North‑south | Terminate TLS 1.2+ (OpenSSL‑GOST default). Use LetsEncrypt or internal CA. | -| East‑west | Compose bridge or K8s ClusterIP only; no public Redis/Mongo ports. | -| Ingress controller | Limit methods to GET, POST, PATCH (no TRACE). | -| Rate‑limits | 40 rps default; tune ScannerPool.Workers and ingress limit‑req to match. | - -##  5 Secrets & key management - -| Secret | Storage | Rotation | -| --------------------------------- | ---------------------------------- | ----------------------------- | -| **Client‑JWT (offline)** | `/var/lib/stella/tokens/client.jwt` (root : 600) | **30 days** – provided by each OUK | -| REDIS_PASS | Docker/K8s secret | 90 days | -| OAuth signing key | /keys/jwt.pem (read‑only mount) | 180 days | -| Cosign public key | /keys/cosign.pub baked into image; | change on every major release | -| Trivy DB mirror token (if remote) | Secret + read‑only | 30 days | - -Never bake secrets into images; always inject at runtime. - -> **Operational tip:** schedule a cron reminding ops 5 days before -> `client.jwt` expiry. The backend also emits a Prometheus metric -> `stella_quota_token_days_remaining`. - -##  6 Image, SBOM & plug‑in supply‑chain controls - -* Images — Pull by digest not latest; verify: - -```bash -cosign verify ghcr.io/stellaops/backend@sha256: \ - --key https://stella-ops.org/keys/cosign.pub -``` - -* SBOM — Each release ships an SPDX file; store alongside images for audit. -* Third‑party plug‑ins — Place in /plugins/; backend will: -* Validate Cosign signature. -* Check [StellaPluginVersion("major.minor")]. -* Refuse to start if Security.DisablePluginUnsigned=false (default). - -##  7 Logging, monitoring & audit - -| Control | Implementation | -| ------------ | ----------------------------------------------------------------- | +#  17 · Security Hardening Guide — **Stella Ops** +*(v2.0 — 12 Jul 2025)* + +> **Audience** — Site‑reliability and platform teams deploying **the open‑source Core** in production or restricted networks. +--- + +##  0 Table of Contents + +1. Threat model (summary) +2. Host‑OS baseline +3. Container & runtime hardening +4. Network‑plane guidance +5. Secrets & key management +6. Image, SBOM & plug‑in supply‑chain controls +7. Logging, monitoring & audit +8. Update & patch strategy +9. Incident‑response workflow +10. Pen‑testing & continuous assurance +11. Contacts & vulnerability disclosure +12. Change log + +--- + +##  1 Threat model (summary) + +| Asset | Threats | Mitigations | +| -------------------- | --------------------- | ---------------------------------------------------------------------- | +| SBOMs & scan results | Disclosure, tamper | TLS‑in‑transit, read‑only Redis volume, RBAC, Cosign‑verified plug‑ins | +| Backend container | RCE, code‑injection | Distroless image, non‑root UID, read‑only FS, seccomp + `CAP_DROP:ALL` | +| Update artefacts | Supply‑chain attack | Cosign‑signed images & SBOMs, enforced by admission controller | +| Admin credentials | Phishing, brute force | OAuth 2.0 with 12‑h token TTL, optional mTLS | + +--- + +##  2 Host‑OS baseline checklist + +| Item | Recommended setting | +| ------------- | --------------------------------------------------------- | +| OS | Ubuntu 22.04 LTS (kernel ≥ 5.15) or Alma 9 | +| Patches | `unattended‑upgrades` or vendor‑equivalent enabled | +| Filesystem | `noexec,nosuid` on `/tmp`, `/var/tmp` | +| Docker Engine | v24.*, API socket root‑owned (`0660`) | +| Auditd | Watch `/etc/docker`, `/usr/bin/docker*` and Compose files | +| Time sync | `chrony` or `systemd‑timesyncd` | + +--- + +##  3 Container & runtime hardening + +###  3.1 Docker Compose reference (`compose-core.yml`) + +```yaml +services: + backend: + image: registry.stella-ops.org/stella-ops/stella-ops: + user: "101:101" # non‑root + read_only: true + security_opt: + - "no-new-privileges:true" + - "seccomp:./seccomp-backend.json" + cap_drop: [ALL] + tmpfs: + - /tmp:size=64m,exec,nosymlink + environment: + - ASPNETCORE_URLS=https://+:8080 + - TLSPROVIDER=OpenSslGost + depends_on: [redis] + networks: [core-net] + healthcheck: + test: ["CMD", "wget", "-qO-", "https://localhost:8080/health"] + interval: 30s + timeout: 5s + retries: 5 + + redis: + image: redis:7.2-alpine + command: ["redis-server", "--requirepass", "${REDIS_PASS}", "--rename-command", "FLUSHALL", ""] + user: "redis" + read_only: true + cap_drop: [ALL] + tmpfs: + - /data + networks: [core-net] + +networks: + core-net: + driver: bridge +``` + +No dedicated “Redis” or “Mongo” sub‑nets are declared; the single bridge network suffices for the default stack. + +###  3.2 Kubernetes deployment highlights + +Use a separate NetworkPolicy that only allows egress from backend to Redis :6379. +securityContext: runAsNonRoot, readOnlyRootFilesystem, allowPrivilegeEscalation: false, drop all capabilities. +PodDisruptionBudget of minAvailable: 1. +Optionally add CosignVerified=true label enforced by an admission controller (e.g. Kyverno or Connaisseur). + +##  4 Network‑plane guidance + +| Plane | Recommendation | +| ------------------ | -------------------------------------------------------------------------- | +| North‑south | Terminate TLS 1.2+ (OpenSSL‑GOST default). Use LetsEncrypt or internal CA. | +| East‑west | Compose bridge or K8s ClusterIP only; no public Redis/Mongo ports. | +| Ingress controller | Limit methods to GET, POST, PATCH (no TRACE). | +| Rate‑limits | 40 rps default; tune ScannerPool.Workers and ingress limit‑req to match. | + +##  5 Secrets & key management + +| Secret | Storage | Rotation | +| --------------------------------- | ---------------------------------- | ----------------------------- | +| **Client‑JWT (offline)** | `/var/lib/stella/tokens/client.jwt` (root : 600) | **30 days** – provided by each OUK | +| REDIS_PASS | Docker/K8s secret | 90 days | +| OAuth signing key | /keys/jwt.pem (read‑only mount) | 180 days | +| Cosign public key | /keys/cosign.pub baked into image; | change on every major release | +| Trivy DB mirror token (if remote) | Secret + read‑only | 30 days | + +Never bake secrets into images; always inject at runtime. + +> **Operational tip:** schedule a cron reminding ops 5 days before +> `client.jwt` expiry. The backend also emits a Prometheus metric +> `stella_quota_token_days_remaining`. + +##  6 Image, SBOM & plug‑in supply‑chain controls + +* Images — Pull by digest not latest; verify: + +```bash +cosign verify ghcr.io/stellaops/backend@sha256: \ + --key https://stella-ops.org/keys/cosign.pub +``` + +* SBOM — Each release ships an SPDX file; store alongside images for audit. +* Third‑party plug‑ins — Place in /plugins/; backend will: +* Validate Cosign signature. +* Check [StellaPluginVersion("major.minor")]. +* Refuse to start if Security.DisablePluginUnsigned=false (default). + +##  7 Logging, monitoring & audit + +| Control | Implementation | +| ------------ | ----------------------------------------------------------------- | | Log format | Serilog JSON; ship via Fluent‑Bit to ELK or Loki | | Metrics | Prometheus /metrics endpoint; default Grafana dashboard in infra/ | | Audit events | Redis stream audit; export daily to SIEM | @@ -159,44 +159,44 @@ cosign verify ghcr.io/stellaops/backend@sha256: \ showing whether a network bypass CIDR allowed the request. Configure your SIEM to alert when unauthenticated requests (`status=401`) appear with `bypass=true`, or when unexpected scopes invoke job triggers. - Detailed monitoring and response guidance lives in `docs/ops/concelier-authority-audit-runbook.md`. - -##  8 Update & patch strategy - -| Layer | Cadence | Method | -| -------------------- | -------------------------------------------------------- | ------------------------------ | -| Backend & CLI images | Monthly or CVE‑driven docker pull + docker compose up -d | + Detailed monitoring and response guidance lives in `docs/modules/concelier/operations/authority-audit-runbook.md`. + +##  8 Update & patch strategy + +| Layer | Cadence | Method | +| -------------------- | -------------------------------------------------------- | ------------------------------ | +| Backend & CLI images | Monthly or CVE‑driven docker pull + docker compose up -d | | Trivy DB | 24 h scheduler via Concelier (vulnerability ingest/merge/export service) | configurable via Concelier scheduler options | -| Docker Engine | vendor LTS | distro package manager | -| Host OS | security repos enabled | unattended‑upgrades | - -##  9 Incident‑response workflow - -* Detect — PagerDuty alert from Prometheus or SIEM. -* Contain — Stop affected Backend container; isolate Redis RDB snapshot. -* Eradicate — Pull verified images, redeploy, rotate secrets. -* Recover — Restore RDB, replay SBOMs if history lost. -* Review — Post‑mortem within 72 h; create follow‑up issues. -* Escalate P1 incidents to (24 × 7). - - -##  10 Pen‑testing & continuous assurance - -| Control | Frequency | Tool/Runner | -|----------------------|-----------------------|-------------------------------------------| -| OWASP ZAP baseline | Each merge to `main` | GitHub Action `zap-baseline-scan` | -| Dependency scanning | Per pull request | Trivy FS + Dependabot | -| External red‑team | Annual or pre‑GA | CREST‑accredited third‑party | - -##  11 Vulnerability disclosure & contact - -* Preferred channel: security@stella‑ops.org (GPG key on website). -* Coordinated disclosure reward: public credit and swag (no monetary bounty at this time). - -##  12 Change log - -| Version | Date | Notes | -| ------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------- | -| v2.0 | 2025‑07‑12 | Full overhaul: host‑OS baseline, supply‑chain signing, removal of unnecessary sub‑nets, role‑based contact e‑mail, K8s guidance. | -| v1.1 | 2025‑07‑09 | Minor fence fixes. | -| v1.0 | 2025‑07‑09 | Original draft. | +| Docker Engine | vendor LTS | distro package manager | +| Host OS | security repos enabled | unattended‑upgrades | + +##  9 Incident‑response workflow + +* Detect — PagerDuty alert from Prometheus or SIEM. +* Contain — Stop affected Backend container; isolate Redis RDB snapshot. +* Eradicate — Pull verified images, redeploy, rotate secrets. +* Recover — Restore RDB, replay SBOMs if history lost. +* Review — Post‑mortem within 72 h; create follow‑up issues. +* Escalate P1 incidents to (24 × 7). + + +##  10 Pen‑testing & continuous assurance + +| Control | Frequency | Tool/Runner | +|----------------------|-----------------------|-------------------------------------------| +| OWASP ZAP baseline | Each merge to `main` | GitHub Action `zap-baseline-scan` | +| Dependency scanning | Per pull request | Trivy FS + Dependabot | +| External red‑team | Annual or pre‑GA | CREST‑accredited third‑party | + +##  11 Vulnerability disclosure & contact + +* Preferred channel: security@stella‑ops.org (GPG key on website). +* Coordinated disclosure reward: public credit and swag (no monetary bounty at this time). + +##  12 Change log + +| Version | Date | Notes | +| ------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------- | +| v2.0 | 2025‑07‑12 | Full overhaul: host‑OS baseline, supply‑chain signing, removal of unnecessary sub‑nets, role‑based contact e‑mail, K8s guidance. | +| v1.1 | 2025‑07‑09 | Minor fence fixes. | +| v1.0 | 2025‑07‑09 | Original draft. | diff --git a/docs/21_INSTALL_GUIDE.md b/docs/21_INSTALL_GUIDE.md index 9b9c28d4..8f51204f 100755 --- a/docs/21_INSTALL_GUIDE.md +++ b/docs/21_INSTALL_GUIDE.md @@ -1,190 +1,190 @@ -# Stella Ops — Installation Guide (Docker & Air‑Gap) - - - -> **Status — public α not yet published.** -> The commands below will work as soon as the first image is tagged -> `registry.stella-ops.org/stella-ops/stella-ops:0.1.0-alpha` -> (target date: **late 2025**). Track progress on the -> [road‑map](/roadmap/). - ---- - -## 0 · Prerequisites - -| Item | Minimum | Notes | -|------|---------|-------| -| Linux | Ubuntu 22.04 LTS / Alma 9 | x86‑64 or arm64 | -| CPU / RAM | 2 vCPU / 2 GiB | Laptop baseline | -| Disk | 10 GiB SSD | SBOM + vuln DB cache | -| Docker | **Engine 25 + Compose v2** | `docker -v` | -| TLS | OpenSSL 1.1 +  | Self‑signed cert generated at first run | - ---- - -## 1 · Connected‑host install (Docker Compose) - -```bash -# 1. Make a working directory -mkdir stella && cd stella - -# 2. Download the signed Compose bundle + example .env -curl -LO https://get.stella-ops.org/releases/latest/.env.example -curl -LO https://get.stella-ops.org/releases/latest/.env.example.sig -curl -LO https://get.stella-ops.org/releases/latest/docker-compose.infrastructure.yml -curl -LO https://get.stella-ops.org/releases/latest/docker-compose.infrastructure.yml.sig -curl -LO https://get.stella-ops.org/releases/latest/docker-compose.stella-ops.yml -curl -LO https://get.stella-ops.org/releases/latest/docker-compose.stella-ops.yml.sig - -# 3. Verify provenance (Cosign public key is stable) -cosign verify-blob \ - --key https://stella-ops.org/keys/cosign.pub \ - --signature .env.example.sig \ - .env.example - -cosign verify-blob \ - --key https://stella-ops.org/keys/cosign.pub \ - --signature docker-compose.infrastructure.yml.sig \ - docker-compose.infrastructure.yml - -cosign verify-blob \ - --key https://stella-ops.org/keys/cosign.pub \ - --signature docker-compose.stella-ops.yml.sig \ - docker-compose.stella-ops.yml - -# 4. Copy .env.example → .env and edit secrets -cp .env.example .env -$EDITOR .env - -# 5. Launch databases (MongoDB + Redis) -docker compose --env-file .env -f docker-compose.infrastructure.yml up -d - -# 6. Launch Stella Ops (first run pulls ~50 MB merged vuln DB) -docker compose --env-file .env -f docker-compose.stella-ops.yml up -d -```` - -*Default login:* `admin / changeme` -UI: [https://\<host\>:8443](https://<host>:8443) (self‑signed certificate) - -> **Pinning best‑practice** – in production environments replace -> `stella-ops:latest` with the immutable digest printed by -> `docker images --digests`. - -> **Repo bundles** – Development, staging, and air‑gapped Compose profiles live -> under `deploy/compose/`, already tied to the release manifests in -> `deploy/releases/`. Helm users can pull the same channel overlays from -> `deploy/helm/stellaops/values-*.yaml` and validate everything with -> `deploy/tools/validate-profiles.sh`. - -### 1.1 · Concelier authority configuration - -The Concelier container reads configuration from `etc/concelier.yaml` plus -`CONCELIER_` environment variables. To enable the new Authority integration: - -1. Add the following keys to `.env` (replace values for your environment): - - ```bash - CONCELIER_AUTHORITY__ENABLED=true - CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true # temporary rollout only - CONCELIER_AUTHORITY__ISSUER="https://authority.internal" - CONCELIER_AUTHORITY__AUDIENCES__0="api://concelier" - CONCELIER_AUTHORITY__REQUIREDSCOPES__0="concelier.jobs.trigger" - CONCELIER_AUTHORITY__REQUIREDSCOPES__1="advisory:read" - CONCELIER_AUTHORITY__REQUIREDSCOPES__2="advisory:ingest" - CONCELIER_AUTHORITY__REQUIREDTENANTS__0="tenant-default" - CONCELIER_AUTHORITY__CLIENTID="concelier-jobs" - CONCELIER_AUTHORITY__CLIENTSCOPES__0="concelier.jobs.trigger" - CONCELIER_AUTHORITY__CLIENTSCOPES__1="advisory:read" - CONCELIER_AUTHORITY__CLIENTSCOPES__2="advisory:ingest" - CONCELIER_AUTHORITY__CLIENTSECRETFILE="/run/secrets/concelier_authority_client" - CONCELIER_AUTHORITY__BYPASSNETWORKS__0="127.0.0.1/32" - CONCELIER_AUTHORITY__BYPASSNETWORKS__1="::1/128" - CONCELIER_AUTHORITY__RESILIENCE__ENABLERETRIES=true - CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__0="00:00:01" - CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__1="00:00:02" - CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__2="00:00:05" - CONCELIER_AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK=true - CONCELIER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE="00:10:00" - ``` - - Store the client secret outside source control (Docker secrets, mounted file, - or Kubernetes Secret). Concelier loads the secret during post-configuration, so - the value never needs to appear in the YAML template. - - Connected sites can keep the retry ladder short (1 s, 2 s, 5 s) so job triggers fail fast when Authority is down. For air‑gapped or intermittently connected deployments, extend `RESILIENCE__OFFLINECACHETOLERANCE` (e.g. `00:30:00`) so cached discovery/JWKS data remains valid while the Offline Kit synchronises upstream changes. - -2. Redeploy Concelier: - - ```bash - docker compose --env-file .env -f docker-compose.stella-ops.yml up -d concelier - ``` - -3. Tail the logs: `docker compose logs -f concelier`. Successful `/jobs*` calls now - emit `Concelier.Authorization.Audit` entries with `route`, `status`, `subject`, - `clientId`, `scopes`, `bypass`, and `remote` fields. 401 denials keep the same - shape—watch for `bypass=True`, which indicates a bypass CIDR accepted an anonymous - call. See `docs/ops/concelier-authority-audit-runbook.md` for a full audit/alerting checklist. - -> **Enforcement deadline** – keep `CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true` -> only while validating the rollout. Set it to `false` (and restart Concelier) -> before **2025-12-31 UTC** to require tokens in production. - ---- - -## 2 · Optional: request a free quota token - -Anonymous installs allow **{{ quota\_anon }} scans per UTC day**. -Email `token@stella-ops.org` to receive a signed JWT that raises the limit to -**{{ quota\_token }} scans/day**. Insert it into `.env`: - -```bash -STELLA_JWT="paste‑token‑here" -docker compose --env-file .env -f docker-compose.stella-ops.yml \ - exec stella-ops stella set-jwt "$STELLA_JWT" -``` - ->  The UI shows a reminder at 200 scans and throttles above the limit but will ->  **never block** your pipeline. - ---- - -## 3 · Air‑gapped install (Offline Update Kit) - -When running on an isolated network use the **Offline Update Kit (OUK)**: - -```bash -# Download & verify on a connected host -curl -LO https://get.stella-ops.org/ouk/stella-ops-offline-kit-v0.1a.tgz -curl -LO https://get.stella-ops.org/ouk/stella-ops-offline-kit-v0.1a.tgz.sig - -cosign verify-blob \ - --key https://stella-ops.org/keys/cosign.pub \ - --signature stella-ops-offline-kit-v0.1a.tgz.sig \ - stella-ops-offline-kit-v0.1a.tgz - -# Transfer → air‑gap → import -docker compose --env-file .env -f docker-compose.stella-ops.yml \ - exec stella admin import-offline-usage-kit stella-ops-offline-kit-v0.1a.tgz -``` - -*Import is atomic; no service downtime.* - -For details see the dedicated [Offline Kit guide](/offline/). - ---- - -## 4 · Next steps - -* **5‑min Quick‑Start:** `/quickstart/` -* **CI recipes:** `docs/ci/20_CI_RECIPES.md` -* **Plug‑in SDK:** `/plugins/` - ---- - -*Generated {{ "now" | date: "%Y‑%m‑%d" }} — build tags inserted at render time.* +# Stella Ops — Installation Guide (Docker & Air‑Gap) + + + +> **Status — public α not yet published.** +> The commands below will work as soon as the first image is tagged +> `registry.stella-ops.org/stella-ops/stella-ops:0.1.0-alpha` +> (target date: **late 2025**). Track progress on the +> [road‑map](/roadmap/). + +--- + +## 0 · Prerequisites + +| Item | Minimum | Notes | +|------|---------|-------| +| Linux | Ubuntu 22.04 LTS / Alma 9 | x86‑64 or arm64 | +| CPU / RAM | 2 vCPU / 2 GiB | Laptop baseline | +| Disk | 10 GiB SSD | SBOM + vuln DB cache | +| Docker | **Engine 25 + Compose v2** | `docker -v` | +| TLS | OpenSSL 1.1 +  | Self‑signed cert generated at first run | + +--- + +## 1 · Connected‑host install (Docker Compose) + +```bash +# 1. Make a working directory +mkdir stella && cd stella + +# 2. Download the signed Compose bundle + example .env +curl -LO https://get.stella-ops.org/releases/latest/.env.example +curl -LO https://get.stella-ops.org/releases/latest/.env.example.sig +curl -LO https://get.stella-ops.org/releases/latest/docker-compose.infrastructure.yml +curl -LO https://get.stella-ops.org/releases/latest/docker-compose.infrastructure.yml.sig +curl -LO https://get.stella-ops.org/releases/latest/docker-compose.stella-ops.yml +curl -LO https://get.stella-ops.org/releases/latest/docker-compose.stella-ops.yml.sig + +# 3. Verify provenance (Cosign public key is stable) +cosign verify-blob \ + --key https://stella-ops.org/keys/cosign.pub \ + --signature .env.example.sig \ + .env.example + +cosign verify-blob \ + --key https://stella-ops.org/keys/cosign.pub \ + --signature docker-compose.infrastructure.yml.sig \ + docker-compose.infrastructure.yml + +cosign verify-blob \ + --key https://stella-ops.org/keys/cosign.pub \ + --signature docker-compose.stella-ops.yml.sig \ + docker-compose.stella-ops.yml + +# 4. Copy .env.example → .env and edit secrets +cp .env.example .env +$EDITOR .env + +# 5. Launch databases (MongoDB + Redis) +docker compose --env-file .env -f docker-compose.infrastructure.yml up -d + +# 6. Launch Stella Ops (first run pulls ~50 MB merged vuln DB) +docker compose --env-file .env -f docker-compose.stella-ops.yml up -d +```` + +*Default login:* `admin / changeme` +UI: [https://\<host\>:8443](https://<host>:8443) (self‑signed certificate) + +> **Pinning best‑practice** – in production environments replace +> `stella-ops:latest` with the immutable digest printed by +> `docker images --digests`. + +> **Repo bundles** – Development, staging, and air‑gapped Compose profiles live +> under `deploy/compose/`, already tied to the release manifests in +> `deploy/releases/`. Helm users can pull the same channel overlays from +> `deploy/helm/stellaops/values-*.yaml` and validate everything with +> `deploy/tools/validate-profiles.sh`. + +### 1.1 · Concelier authority configuration + +The Concelier container reads configuration from `etc/concelier.yaml` plus +`CONCELIER_` environment variables. To enable the new Authority integration: + +1. Add the following keys to `.env` (replace values for your environment): + + ```bash + CONCELIER_AUTHORITY__ENABLED=true + CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true # temporary rollout only + CONCELIER_AUTHORITY__ISSUER="https://authority.internal" + CONCELIER_AUTHORITY__AUDIENCES__0="api://concelier" + CONCELIER_AUTHORITY__REQUIREDSCOPES__0="concelier.jobs.trigger" + CONCELIER_AUTHORITY__REQUIREDSCOPES__1="advisory:read" + CONCELIER_AUTHORITY__REQUIREDSCOPES__2="advisory:ingest" + CONCELIER_AUTHORITY__REQUIREDTENANTS__0="tenant-default" + CONCELIER_AUTHORITY__CLIENTID="concelier-jobs" + CONCELIER_AUTHORITY__CLIENTSCOPES__0="concelier.jobs.trigger" + CONCELIER_AUTHORITY__CLIENTSCOPES__1="advisory:read" + CONCELIER_AUTHORITY__CLIENTSCOPES__2="advisory:ingest" + CONCELIER_AUTHORITY__CLIENTSECRETFILE="/run/secrets/concelier_authority_client" + CONCELIER_AUTHORITY__BYPASSNETWORKS__0="127.0.0.1/32" + CONCELIER_AUTHORITY__BYPASSNETWORKS__1="::1/128" + CONCELIER_AUTHORITY__RESILIENCE__ENABLERETRIES=true + CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__0="00:00:01" + CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__1="00:00:02" + CONCELIER_AUTHORITY__RESILIENCE__RETRYDELAYS__2="00:00:05" + CONCELIER_AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK=true + CONCELIER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE="00:10:00" + ``` + + Store the client secret outside source control (Docker secrets, mounted file, + or Kubernetes Secret). Concelier loads the secret during post-configuration, so + the value never needs to appear in the YAML template. + + Connected sites can keep the retry ladder short (1 s, 2 s, 5 s) so job triggers fail fast when Authority is down. For air‑gapped or intermittently connected deployments, extend `RESILIENCE__OFFLINECACHETOLERANCE` (e.g. `00:30:00`) so cached discovery/JWKS data remains valid while the Offline Kit synchronises upstream changes. + +2. Redeploy Concelier: + + ```bash + docker compose --env-file .env -f docker-compose.stella-ops.yml up -d concelier + ``` + +3. Tail the logs: `docker compose logs -f concelier`. Successful `/jobs*` calls now + emit `Concelier.Authorization.Audit` entries with `route`, `status`, `subject`, + `clientId`, `scopes`, `bypass`, and `remote` fields. 401 denials keep the same + shape—watch for `bypass=True`, which indicates a bypass CIDR accepted an anonymous + call. See `docs/modules/concelier/operations/authority-audit-runbook.md` for a full audit/alerting checklist. + +> **Enforcement deadline** – keep `CONCELIER_AUTHORITY__ALLOWANONYMOUSFALLBACK=true` +> only while validating the rollout. Set it to `false` (and restart Concelier) +> before **2025-12-31 UTC** to require tokens in production. + +--- + +## 2 · Optional: request a free quota token + +Anonymous installs allow **{{ quota\_anon }} scans per UTC day**. +Email `token@stella-ops.org` to receive a signed JWT that raises the limit to +**{{ quota\_token }} scans/day**. Insert it into `.env`: + +```bash +STELLA_JWT="paste‑token‑here" +docker compose --env-file .env -f docker-compose.stella-ops.yml \ + exec stella-ops stella set-jwt "$STELLA_JWT" +``` + +>  The UI shows a reminder at 200 scans and throttles above the limit but will +>  **never block** your pipeline. + +--- + +## 3 · Air‑gapped install (Offline Update Kit) + +When running on an isolated network use the **Offline Update Kit (OUK)**: + +```bash +# Download & verify on a connected host +curl -LO https://get.stella-ops.org/ouk/stella-ops-offline-kit-v0.1a.tgz +curl -LO https://get.stella-ops.org/ouk/stella-ops-offline-kit-v0.1a.tgz.sig + +cosign verify-blob \ + --key https://stella-ops.org/keys/cosign.pub \ + --signature stella-ops-offline-kit-v0.1a.tgz.sig \ + stella-ops-offline-kit-v0.1a.tgz + +# Transfer → air‑gap → import +docker compose --env-file .env -f docker-compose.stella-ops.yml \ + exec stella admin import-offline-usage-kit stella-ops-offline-kit-v0.1a.tgz +``` + +*Import is atomic; no service downtime.* + +For details see the dedicated [Offline Kit guide](/offline/). + +--- + +## 4 · Next steps + +* **5‑min Quick‑Start:** `/quickstart/` +* **CI recipes:** `docs/ci/20_CI_RECIPES.md` +* **Plug‑in SDK:** `/plugins/` + +--- + +*Generated {{ "now" | date: "%Y‑%m‑%d" }} — build tags inserted at render time.* diff --git a/docs/24_OFFLINE_KIT.md b/docs/24_OFFLINE_KIT.md index f5c358ad..b34fbaf1 100755 --- a/docs/24_OFFLINE_KIT.md +++ b/docs/24_OFFLINE_KIT.md @@ -1,15 +1,15 @@ -# Offline Update Kit (OUK) — Air‑Gap Bundle - - - -The **Offline Update Kit** packages everything Stella Ops needs to run on a -completely isolated network: - +# Offline Update Kit (OUK) — Air‑Gap Bundle + + + +The **Offline Update Kit** packages everything Stella Ops needs to run on a +completely isolated network: + | Component | Contents | |-----------|----------| | **Merged vulnerability feeds** | OSV, GHSA plus optional NVD 2.0, CNNVD, CNVD, ENISA, JVN and BDU | @@ -94,7 +94,7 @@ cosign verify-blob \ ```` **CLI shortcut.** `stellaops-cli offline kit pull --destination ./offline-kit` downloads the bundle, manifest, and detached signatures in one step, resumes partial transfers, and writes a `.metadata.json` summary for later import. - + Verification prints **OK** and the SHA‑256 digest; cross‑check against the [changelog](https://git.stella-ops.org/stella-ops/offline-kit/-/releases). @@ -228,7 +228,7 @@ tar -tzf stella-ops-offline-kit-.tgz 'plugins/scanner/analyzers/lang/Stell The manifest lookup above and this `tar` listing should both surface the Go analyzer DLL, PDB, and manifest entries before the kit is promoted. -> **Release guardrail.** The automated release pipeline now publishes the Python plug-in from source and executes `dotnet run --project tools/LanguageAnalyzerSmoke --configuration Release -- --repo-root ` to validate manifest integrity and cold/warm determinism within the < 30 s / < 5 s budgets (differences versus repository goldens are logged for triage). Run `ops/offline-kit/run-python-analyzer-smoke.sh` locally before shipping a refreshed kit if you rebuild artefacts outside CI or when preparing the air-gap bundle. +> **Release guardrail.** The automated release pipeline now publishes the Python plug-in from source and executes `dotnet run --project src/Tools/LanguageAnalyzerSmoke --configuration Release -- --repo-root ` to validate manifest integrity and cold/warm determinism within the < 30 s / < 5 s budgets (differences versus repository goldens are logged for triage). Run `ops/offline-kit/run-python-analyzer-smoke.sh` locally before shipping a refreshed kit if you rebuild artefacts outside CI or when preparing the air-gap bundle. ### Debug store mirror @@ -246,41 +246,41 @@ The script mirrors the debug tree into the Offline Kit staging directory, verifi --- ## 3 · Delta patch workflow - -1. **Connected site** fetches `stella-ouk-YYYY‑MM‑DD.delta.tgz`. -2. Transfer via any medium (USB, portable disk). -3. `stella admin import-offline-usage-kit ` applies only changed CVE rows & images. - -Daily deltas are **< 30 MB**; weekly roll‑up produces a fresh full kit. - ---- - -## 4 · Quota behaviour offline - -The scanner enforces the same fair‑use limits offline: - -* **Anonymous:** {{ quota\_anon }} scans per UTC day -* **Free JWT:** {{ quota\_token }} scans per UTC day - -Soft reminder at 200 scans; throttle above the ceiling but **never block**. -See the detailed rules in -[`33_333_QUOTA_OVERVIEW.md`](33_333_QUOTA_OVERVIEW.md). - ---- - -## 5 · Troubleshooting - -| Symptom | Explanation | Fix | -| -------------------------------------- | ---------------------------------------- | ------------------------------------- | -| `could not verify SBOM hash` | Bundle corrupted in transit | Re‑download / re‑copy | -| Import hangs at `Applying feeds…` | Low disk space in `/var/lib/stella` | Free ≥ 2 GiB before retry | -| `quota exceeded` same day after import | Import resets counters at UTC 00:00 only | Wait until next UTC day or load a JWT | - ---- - -## 6 · Related documentation - + +1. **Connected site** fetches `stella-ouk-YYYY‑MM‑DD.delta.tgz`. +2. Transfer via any medium (USB, portable disk). +3. `stella admin import-offline-usage-kit ` applies only changed CVE rows & images. + +Daily deltas are **< 30 MB**; weekly roll‑up produces a fresh full kit. + +--- + +## 4 · Quota behaviour offline + +The scanner enforces the same fair‑use limits offline: + +* **Anonymous:** {{ quota\_anon }} scans per UTC day +* **Free JWT:** {{ quota\_token }} scans per UTC day + +Soft reminder at 200 scans; throttle above the ceiling but **never block**. +See the detailed rules in +[`33_333_QUOTA_OVERVIEW.md`](33_333_QUOTA_OVERVIEW.md). + +--- + +## 5 · Troubleshooting + +| Symptom | Explanation | Fix | +| -------------------------------------- | ---------------------------------------- | ------------------------------------- | +| `could not verify SBOM hash` | Bundle corrupted in transit | Re‑download / re‑copy | +| Import hangs at `Applying feeds…` | Low disk space in `/var/lib/stella` | Free ≥ 2 GiB before retry | +| `quota exceeded` same day after import | Import resets counters at UTC 00:00 only | Wait until next UTC day or load a JWT | + +--- + +## 6 · Related documentation + * **Install guide:** `/install/#air-gapped` * **Sovereign mode rationale:** `/sovereign/` * **Security policy:** `/security/#reporting-a-vulnerability` -* **CERT-Bund snapshots:** `python tools/certbund_offline_snapshot.py --help` (see `docs/ops/concelier-certbund-operations.md`) +* **CERT-Bund snapshots:** `python src/Tools/certbund_offline_snapshot.py --help` (see `docs/modules/concelier/operations/connectors/certbund.md`) diff --git a/docs/AGENTS.md b/docs/AGENTS.md index a501466b..efe4242a 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -1,20 +1,20 @@ -# Docs & Enablement Guild - -## Mission -Produce and maintain offline-friendly documentation for StellaOps modules, covering architecture, configuration, operator workflows, and developer onboarding. - -## Scope Highlights -- Authority docs (`docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, upcoming `docs/11_AUTHORITY.md`). -- Concelier quickstarts, CLI guides, Offline Kit manuals. -- Release notes and migration playbooks. - -## Operating Principles -- Keep guides deterministic and in sync with shipped configuration samples. -- Prefer tables/checklists for operator steps; flag security-sensitive actions. -- When work involves a specific `StellaOps.` project, consult both `docs/07_HIGH_LEVEL_ARCHITECTURE.md` and the matching dossier `docs/ARCHITECTURE_.md` before drafting or editing content. -- Update `docs/TASKS.md` whenever work items change status (TODO/DOING/REVIEW/DONE/BLOCKED). - -## Coordination -- Authority Core & Plugin teams for auth-related changes. -- Security Guild for threat-model outputs and mitigations. -- DevEx for tooling diagrams and documentation pipeline. +# Docs & Enablement Guild + +## Mission +Produce and maintain offline-friendly documentation for StellaOps modules, covering architecture, configuration, operator workflows, and developer onboarding. + +## Scope Highlights +- Authority docs (`docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, upcoming `docs/11_AUTHORITY.md`). +- Concelier quickstarts, CLI guides, Offline Kit manuals. +- Release notes and migration playbooks. + +## Operating Principles +- Keep guides deterministic and in sync with shipped configuration samples. +- Prefer tables/checklists for operator steps; flag security-sensitive actions. +- When work involves a specific `StellaOps.` project, consult both `docs/07_HIGH_LEVEL_ARCHITECTURE.md` and the matching dossier `docs/modules//architecture.md` before drafting or editing content. +- Update `docs/TASKS.md` whenever work items change status (TODO/DOING/REVIEW/DONE/BLOCKED). + +## Coordination +- Authority Core & Plugin teams for auth-related changes. +- Security Guild for threat-model outputs and mitigations. +- DevEx for tooling diagrams and documentation pipeline. diff --git a/docs/README.md b/docs/README.md index 2491e2be..86540f39 100755 --- a/docs/README.md +++ b/docs/README.md @@ -36,21 +36,21 @@ Everything here is open‑source and versioned — when you check out a git ta - **07 – [High‑Level Architecture](07_HIGH_LEVEL_ARCHITECTURE.md)** - **08 – [Architecture Decision Records](adr/index.md)** - **08 – Module Architecture Dossiers** - - [Architecture Overview](architecture/overview.md) - - [Scanner](ARCHITECTURE_SCANNER.md) - - [Concelier](ARCHITECTURE_CONCELIER.md) - - [Excititor](ARCHITECTURE_EXCITITOR.md) - - [Excititor Mirrors](ARCHITECTURE_EXCITITOR_MIRRORS.md) - - [Signer](ARCHITECTURE_SIGNER.md) - - [Attestor](ARCHITECTURE_ATTESTOR.md) - - [Authority](ARCHITECTURE_AUTHORITY.md) - - [Policy Engine](architecture/policy-engine.md) - - [Notify](ARCHITECTURE_NOTIFY.md) - - [Scheduler](ARCHITECTURE_SCHEDULER.md) - - [CLI](ARCHITECTURE_CLI.md) - - [Web UI](ARCHITECTURE_UI.md) - - [Zastava Runtime](ARCHITECTURE_ZASTAVA.md) - - [Release & Operations](ARCHITECTURE_DEVOPS.md) + - [Architecture Overview](modules/platform/architecture-overview.md) + - [Scanner](modules/scanner/architecture.md) + - [Concelier](modules/concelier/architecture.md) + - [Excititor](modules/excititor/architecture.md) + - [Excititor Mirrors](modules/excititor/mirrors.md) + - [Signer](modules/signer/architecture.md) + - [Attestor](modules/attestor/architecture.md) + - [Authority](modules/authority/architecture.md) + - [Policy Engine](modules/policy/architecture.md) + - [Notify](modules/notify/architecture.md) + - [Scheduler](modules/scheduler/architecture.md) + - [CLI](modules/cli/architecture.md) + - [Web UI](modules/ui/architecture.md) + - [Zastava Runtime](modules/zastava/architecture.md) + - [Release & Operations](modules/devops/architecture.md) - **09 – [API & CLI Reference](09_API_CLI_REFERENCE.md)** - **10 – [Plug‑in SDK Guide](10_PLUGIN_SDK_GUIDE.md)** - **10 – [Concelier CLI Quickstart](10_CONCELIER_CLI_QUICKSTART.md)** @@ -60,13 +60,14 @@ Everything here is open‑source and versioned — when you check out a git ta - **31 – [Aggregation-Only Contract Reference](ingestion/aggregation-only-contract.md)** - **31 – [Advisory Observations & Linksets](advisories/aggregation.md)** - **31 – [VEX Observations & Linksets](vex/aggregation.md)** +- **32 – [Entry-Point Detection Playbook](modules/scanner/operations/entrypoint.md)** - **30 – Developer Templates** - [Excititor Connector Skeleton](dev/templates/excititor-connector/) - **11 – [Authority Service](11_AUTHORITY.md)** - **11 – [Data Schemas](11_DATA_SCHEMAS.md)** - **12 – [Performance Workbook](12_PERFORMANCE_WORKBOOK.md)** - **13 – [Release‑Engineering Playbook](13_RELEASE_ENGINEERING_PLAYBOOK.md)** -- **20 – [CLI AOC Commands Reference](cli/cli-reference.md)** +- **20 – [CLI AOC Commands Reference](modules/cli/guides/cli-reference.md)** - **20 – [Console CLI Parity Matrix](cli-vs-ui-parity.md)** - **60 – [Policy Engine Overview](policy/overview.md)** - **61 – [Policy DSL Grammar](policy/dsl.md)** @@ -74,7 +75,7 @@ Everything here is open‑source and versioned — when you check out a git ta - **63 – [Policy Runs & Orchestration](policy/runs.md)** - **64 – [Policy Exception Effects](policy/exception-effects.md)** - **65 – [Policy Engine REST API](api/policy.md)** -- **66 – [Policy CLI Guide](cli/policy.md)** +- **66 – [Policy CLI Guide](modules/cli/guides/policy.md)** - **67 – [Policy Editor Workspace](ui/policy-editor.md)** - **68 – [Policy Observability](observability/policy.md)** - **69 – [Console Observability](observability/ui-telemetry.md)** @@ -84,14 +85,14 @@ Everything here is open‑source and versioned — when you check out a git ta - **72 – [Policy FAQ](faq/policy-faq.md)** - **73 – [Policy Run DTOs](../src/Scheduler/__Libraries/StellaOps.Scheduler.Models/docs/SCHED-MODELS-20-001-POLICY-RUNS.md)** - **30 – [Fixture Maintenance](dev/fixtures.md)** -- **74 – [Export Center Overview](export-center/overview.md)** -- **75 – [Export Center Architecture](export-center/architecture.md)** -- **76 – [Export Center Profiles](export-center/profiles.md)** -- **77 – [Export Center API Reference](export-center/api.md)** -- **78 – [Export Center CLI Guide](export-center/cli.md)** -- **79 – [Export Center Trivy Adapters](export-center/trivy-adapter.md)** -- **80 – [Export Center Mirror Bundles](export-center/mirror-bundles.md)** -- **81 – [Export Center Provenance & Signing](export-center/provenance-and-signing.md)** +- **74 – [Export Center Overview](modules/export-center/overview.md)** +- **75 – [Export Center Architecture](modules/export-center/architecture.md)** +- **76 – [Export Center Profiles](modules/export-center/profiles.md)** +- **77 – [Export Center API Reference](modules/export-center/api.md)** +- **78 – [Export Center CLI Guide](modules/export-center/cli.md)** +- **79 – [Export Center Trivy Adapters](modules/export-center/trivy-adapter.md)** +- **80 – [Export Center Mirror Bundles](modules/export-center/mirror-bundles.md)** +- **81 – [Export Center Provenance & Signing](modules/export-center/provenance-and-signing.md)** ### User & operator guides - **14 – [Glossary](14_GLOSSARY_OF_TERMS.md)** @@ -148,7 +149,7 @@ Everything here is open‑source and versioned — when you check out a git ta > Imposed rule: Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - **Aggregation-Only Contract (AOC).** Ingestion services aggregate and link facts only—derived precedence, severity, and safe-fix hints live in Policy overlays and dedicated explorers. Review [`implplan/AGENTS.md`](implplan/AGENTS.md) and the AOC guardrails in [`aoc/aoc-guardrails.md`](aoc/aoc-guardrails.md). -- **Cartographer owns graphs.** SBOM Service emits projections/events; Cartographer (`CARTO-GRAPH-21-00x`) builds graph storage, overlays, and tiles. See `ARCHITECTURE_CONCELIER.md` (Cartographer handshake section) for handoff boundaries. +- **Cartographer owns graphs.** SBOM Service emits projections/events; Cartographer (`CARTO-GRAPH-21-00x`) builds graph storage, overlays, and tiles. See `modules/concelier/architecture.md` (Cartographer handshake section) for handoff boundaries. - **Notifier replaces legacy Notify.** Sprint‑15 `StellaOps.Notify.*` tasks are frozen; use the Notifications Studio/Notifier backlogs (`NOTIFY-SVC-38..40`, `WEB-NOTIFY-3x-00x`, `CLI-NOTIFY-3x-00x`). - **Dedicated services for Vuln & Policy.** Vuln Explorer work flows through `src/VulnExplorer/StellaOps.VulnExplorer.Api`/Console/CLI (Sprint 29); gateway routes proxy only. Policy Engine remains the sole source for precedence/suppression overlays. - **Cleanup log.** The backlog consolidation summary lives in [`backlog/2025-10-cleanup.md`](backlog/2025-10-cleanup.md). diff --git a/docs/TASKS.md b/docs/TASKS.md index 2d529135..ac7b9456 100644 --- a/docs/TASKS.md +++ b/docs/TASKS.md @@ -1,381 +1,381 @@ -# Docs Guild Task Board (UTC 2025-10-10) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOC7.README-INDEX | DONE (2025-10-17) | Docs Guild | — | Refresh index docs (docs/README.md + root README) after architecture dossier split and Offline Kit overhaul. | ✅ ToC reflects new component architecture docs; ✅ root README highlights updated doc set; ✅ Offline Kit guide linked correctly. | -| DOC4.AUTH-PDG | DONE (2025-10-19) | Docs Guild, Plugin Team | PLG6.DOC | Copy-edit `docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, export lifecycle diagram, add LDAP RFC cross-link. | ✅ PR merged with polish; ✅ Diagram committed; ✅ Slack handoff posted. | -| DOC1.AUTH | DONE (2025-10-12) | Docs Guild, Authority Core | CORE5B.DOC | Draft `docs/11_AUTHORITY.md` covering architecture, configuration, bootstrap flows. | ✅ Architecture + config sections approved by Core; ✅ Samples reference latest options; ✅ Offline note added. | -| DOC3.Concelier-Authority | DONE (2025-10-12) | Docs Guild, DevEx | FSR4 | Polish operator/runbook sections (DOC3/DOC5) to document Concelier authority rollout, bypass logging, and enforcement checklist. | ✅ DOC3/DOC5 updated with audit runbook references; ✅ enforcement deadline highlighted; ✅ Docs guild sign-off. | -| DOC5.Concelier-Runbook | DONE (2025-10-12) | Docs Guild | DOC3.Concelier-Authority | Produce dedicated Concelier authority audit runbook covering log fields, monitoring recommendations, and troubleshooting steps. | ✅ Runbook published; ✅ linked from DOC3/DOC5; ✅ alerting guidance included. | -| FEEDDOCS-DOCS-05-001 | DONE (2025-10-11) | Docs Guild | FEEDMERGE-ENGINE-04-001, FEEDMERGE-ENGINE-04-002 | Publish Concelier conflict resolution runbook covering precedence workflow, merge-event auditing, and Sprint 3 metrics. | ✅ `docs/ops/concelier-conflict-resolution.md` committed; ✅ metrics/log tables align with latest merge code; ✅ Ops alert guidance handed to Concelier team. | -| FEEDDOCS-DOCS-05-002 | DONE (2025-10-16) | Docs Guild, Concelier Ops | FEEDDOCS-DOCS-05-001 | Ops sign-off captured: conflict runbook circulated, alert thresholds tuned, and rollout decisions documented in change log. | ✅ Ops review recorded; ✅ alert thresholds finalised using `docs/ops/concelier-authority-audit-runbook.md`; ✅ change-log entry linked from runbook once GHSA/NVD/OSV regression fixtures land. | -| DOCS-ADR-09-001 | DONE (2025-10-19) | Docs Guild, DevEx | — | Establish ADR process (`docs/adr/0000-template.md`) and document usage guidelines. | Template published; README snippet linking ADR process; announcement posted (`docs/updates/2025-10-18-docs-guild.md`). | -| DOCS-EVENTS-09-002 | DONE (2025-10-19) | Docs Guild, Platform Events | SCANNER-EVENTS-15-201 | Publish event schema catalog (`docs/events/`) for `scanner.report.ready@1`, `scheduler.rescan.delta@1`, `attestor.logged@1`. | Schemas validated (Ajv CI hooked); docs/events/README summarises usage; Platform Events notified via `docs/updates/2025-10-18-docs-guild.md`. | -| DOCS-EVENTS-09-003 | DONE (2025-10-19) | Docs Guild | DOCS-EVENTS-09-002 | Add human-readable envelope field references and canonical payload samples for published events, including offline validation workflow. | Tables explain common headers/payload segments; versioned sample payloads committed; README links to validation instructions and samples. | -| DOCS-EVENTS-09-004 | DONE (2025-10-19) | Docs Guild, Scanner WebService | SCANNER-EVENTS-15-201 | Refresh scanner event docs to mirror DSSE-backed report fields, document `scanner.scan.completed`, and capture canonical sample validation. | Schemas updated for new payload shape; README references DSSE reuse and validation test; samples align with emitted events. | -| PLATFORM-EVENTS-09-401 | DONE (2025-10-21) | Platform Events Guild | DOCS-EVENTS-09-003 | Embed canonical event samples into contract/integration tests and ensure CI validates payloads against published schemas. | Notify models tests now run schema validation against `docs/events/*.json`, event schemas allow optional `attributes`, and docs capture the new validation workflow. | -| RUNTIME-GUILD-09-402 | DONE (2025-10-19) | Runtime Guild | SCANNER-POLICY-09-107 | Confirm Scanner WebService surfaces `quietedFindingCount` and progress hints to runtime consumers; document readiness checklist. | Runtime verification run captures enriched payload; checklist/doc updates merged; stakeholders acknowledge availability. | -| DOCS-CONCELIER-07-201 | DONE (2025-10-22) | Docs Guild, Concelier WebService | FEEDWEB-DOCS-01-001 | Final editorial review and publish pass for Concelier authority toggle documentation (Quickstart + operator guide). | Review feedback resolved, publish PR merged, release notes updated with documentation pointer. | -| DOCS-RUNTIME-17-004 | DONE (2025-10-26) | Docs Guild, Runtime Guild | SCANNER-EMIT-17-701, ZASTAVA-OBS-17-005, DEVOPS-REL-17-002 | Document build-id workflows: SBOM exposure, runtime event payloads (`process.buildId`), Scanner `/policy/runtime` response (`buildIds` list), debug-store layout, and operator guidance for symbol retrieval. | Architecture + operator docs updated with build-id sections (Observer, Scanner, CLI), examples show `readelf` output + debuginfod usage, references linked from Offline Kit/Release guides + CLI help. | -| DOCS-OBS-50-001 | BLOCKED (2025-10-26) | Docs Guild, Observability Guild | TELEMETRY-OBS-50-001 | Publish `/docs/observability/overview.md` introducing scope, imposed rule banner, architecture diagram, and tenant guarantees. | Doc merged with imposed rule banner; diagram committed; cross-links to telemetry stack + evidence locker docs. | -> Blocked: waiting on telemetry core deliverable (TELEMETRY-OBS-50-001) to finalise architecture details and diagrams. -| DOCS-OBS-50-002 | TODO | Docs Guild, Security Guild | TELEMETRY-OBS-50-002 | Author `/docs/observability/telemetry-standards.md` detailing common fields, scrubbing policy, sampling defaults, and redaction override procedure. | Doc merged; imposed rule banner present; examples validated with telemetry fixtures; security review sign-off captured. | -| DOCS-OBS-50-003 | TODO | Docs Guild, Observability Guild | TELEMETRY-OBS-50-001 | Create `/docs/observability/logging.md` covering structured log schema, dos/don'ts, tenant isolation, and copyable examples. | Doc merged with banner; sample logs redacted; lint passes; linked from coding standards. | -| DOCS-OBS-50-004 | TODO | Docs Guild, Observability Guild | TELEMETRY-OBS-50-002 | Draft `/docs/observability/tracing.md` explaining context propagation, async linking, CLI header usage, and sampling strategies. | Doc merged; imposed rule banner included; diagrams updated; references to CLI/Console features added. | -| DOCS-OBS-51-001 | TODO | Docs Guild, DevOps Guild | WEB-OBS-51-001, DEVOPS-OBS-51-001 | Publish `/docs/observability/metrics-and-slos.md` cataloging metrics, SLO targets, burn rate policies, and alert runbooks. | Doc merged with banner; SLO tables verified; alert workflows linked to incident runbook. | -| DOCS-SEC-OBS-50-001 | TODO | Docs Guild, Security Guild | TELEMETRY-OBS-51-002 | Update `/docs/security/redaction-and-privacy.md` to cover telemetry privacy controls, tenant opt-in debug, and imposed rule reminder. | Doc merged; redaction matrix updated; banner present; security sign-off recorded. | -| DOCS-INSTALL-50-001 | TODO | Docs Guild, DevOps Guild | DEVOPS-OBS-50-003 | Add `/docs/install/telemetry-stack.md` with collector deployment, exporter options, offline kit notes, and imposed rule banner. | Doc merged; install steps verified on air-gapped profile; banner present; screenshots attached. | -| DOCS-FORENSICS-53-001 | TODO | Docs Guild, Evidence Locker Guild | EVID-OBS-53-003 | Publish `/docs/forensics/evidence-locker.md` describing bundle formats, WORM options, retention, legal hold, and imposed rule banner. | Doc merged; manifest examples validated; banner present; legal hold steps aligned with API. | -| DOCS-FORENSICS-53-002 | TODO | Docs Guild, Provenance Guild | PROV-OBS-54-001 | Release `/docs/forensics/provenance-attestation.md` covering DSSE schema, signing process, verification workflow, and imposed rule banner. | Doc merged; sample statements reference fixtures; banner included; verification steps tested. | -| DOCS-FORENSICS-53-003 | TODO | Docs Guild, Timeline Indexer Guild | TIMELINE-OBS-52-003 | Publish `/docs/forensics/timeline.md` with schema, event kinds, filters, query examples, and imposed rule banner. | Doc merged; query examples validated; banner present; linked from Console/CLI docs. | -| DOCS-CONSOLE-OBS-52-001 | TODO | Docs Guild, Console Guild | CONSOLE-OBS-51-001 | Document `/docs/console/observability.md` showcasing Observability Hub widgets, trace/log search, imposed rule banner, and accessibility tips. | Doc merged; screenshots updated; banner present; navigation steps verified. | -| DOCS-CONSOLE-OBS-52-002 | TODO | Docs Guild, Console Guild | CONSOLE-OBS-52-002, CONSOLE-OBS-53-001 | Publish `/docs/console/forensics.md` covering timeline explorer, evidence viewer, attestation verifier, imposed rule banner, and troubleshooting. | Doc merged; banner included; workflows validated via Playwright capture; troubleshooting section populated. | -| DOCS-CLI-OBS-52-001 | TODO | Docs Guild, DevEx/CLI Guild | CLI-OBS-52-001 | Create `/docs/cli/observability.md` detailing `stella obs` commands, examples, exit codes, imposed rule banner, and scripting tips. | Doc merged; examples tested; banner included; CLI parity matrix updated. | -| DOCS-CLI-FORENSICS-53-001 | TODO | Docs Guild, DevEx/CLI Guild | CLI-FORENSICS-54-001 | Publish `/docs/cli/forensics.md` for snapshot/verify/attest commands with sample outputs, imposed rule banner, and offline workflows. | Doc merged; sample bundles verified; banner present; offline notes cross-linked. | -| DOCS-RUNBOOK-55-001 | TODO | Docs Guild, Ops Guild | DEVOPS-OBS-55-001, WEB-OBS-55-001 | Author `/docs/runbooks/incidents.md` describing incident mode activation, escalation steps, retention impact, verification checklist, and imposed rule banner. | Doc merged; runbook rehearsed; banner included; linked from alerts. | -| DOCS-AOC-19-001 | DONE (2025-10-26) | Docs Guild, Concelier Guild | CONCELIER-WEB-AOC-19-001, EXCITITOR-WEB-AOC-19-001 | Author `/docs/ingestion/aggregation-only-contract.md` covering philosophy, invariants, schemas, error codes, migration, observability, and security checklist. | New doc published with compliance checklist; cross-links from existing docs added. | -| DOCS-AOC-19-002 | DONE (2025-10-26) | Docs Guild, Architecture Guild | DOCS-AOC-19-001 | Update `/docs/architecture/overview.md` to include AOC boundary, raw stores, and sequence diagram (fetch → guard → raw insert → policy evaluation). | Overview doc updated with diagrams/text; lint passes; stakeholders sign off. | -| DOCS-AOC-19-003 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-AOC-19-003 | Refresh `/docs/architecture/policy-engine.md` clarifying ingestion boundary, raw inputs, and policy-only derived data. | Doc highlights raw-only ingestion contract, updated diagrams merge, compliance checklist added. | -| DOCS-AOC-19-004 | DONE (2025-10-26) | Docs Guild, UI Guild | UI-AOC-19-001 | Extend `/docs/ui/console.md` with Sources dashboard tiles, violation drill-down workflow, and verification action. | UI doc updated with screenshots/flow descriptions, compliance checklist appended. | -> DOCS-AOC-19-004: Architecture overview & policy-engine updates landed 2025-10-26; incorporate the new AOC boundary diagrams and metrics references. -| DOCS-AOC-19-005 | DONE (2025-10-26) | Docs Guild, CLI Guild | CLI-AOC-19-003 | Update `/docs/cli/cli-reference.md` with `stella sources ingest --dry-run` and `stella aoc verify` usage, exit codes, and offline notes. | CLI reference + quickstart sections updated; examples validated; compliance checklist added. | -> DOCS-AOC-19-005: New ingestion reference + architecture overview published 2025-10-26; ensure CLI docs link to both and surface AOC exit codes mapping. -| DOCS-AOC-19-006 | DONE (2025-10-26) | Docs Guild, Observability Guild | CONCELIER-WEB-AOC-19-002, EXCITITOR-WEB-AOC-19-002 | Document new metrics/traces/log keys in `/docs/observability/observability.md`. | Observability doc lists new metrics/traces/log fields; dashboards referenced; compliance checklist appended. | -| DOCS-AOC-19-007 | DONE (2025-10-26) | Docs Guild, Authority Core | AUTH-AOC-19-001 | Update `/docs/security/authority-scopes.md` with new ingestion scopes and tenancy enforcement notes. | Doc reflects new scopes, sample policies updated, compliance checklist added. | -| DOCS-AOC-19-008 | DONE (2025-10-26) | Docs Guild, DevOps Guild | DEVOPS-AOC-19-002 | Refresh `/docs/deploy/containers.md` to cover validator enablement, guard env flags, and read-only verify user. | Deploy doc updated; offline kit section mentions validator scripts; compliance checklist appended. | -| DOCS-AOC-19-009 | DONE (2025-10-26) | Docs Guild, Authority Core | AUTH-AOC-19-001 | Update AOC docs/samples to reflect new `advisory:*`, `vex:*`, and `aoc:verify` scopes. | Docs reference new scopes, samples aligned, compliance checklist updated. | - -## Air-Gapped Mode (Epic 16) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-AIRGAP-56-001 | TODO | Docs Guild, AirGap Controller Guild | AIRGAP-CTL-56-002 | Publish `/docs/airgap/overview.md` outlining modes, lifecycle, responsibilities, and imposed rule banner. | Doc merged; banner present; diagrams included. | -| DOCS-AIRGAP-56-002 | TODO | Docs Guild, DevOps Guild | DEVOPS-AIRGAP-56-001 | Author `/docs/airgap/sealing-and-egress.md` covering network policies, EgressPolicy facade usage, and verification steps. | Doc merged; examples validated; banner included. | -| DOCS-AIRGAP-56-003 | TODO | Docs Guild, Exporter Guild | EXPORT-AIRGAP-56-001 | Create `/docs/airgap/mirror-bundles.md` describing bundle format, DSSE/TUF/Merkle validation, creation/import workflows. | Doc merged; sample commands verified; banner present. | -| DOCS-AIRGAP-56-004 | TODO | Docs Guild, Deployment Guild | DEVOPS-AIRGAP-56-003 | Publish `/docs/airgap/bootstrap.md` detailing Bootstrap Pack creation, validation, and install procedures. | Doc merged; checklist appended; screenshots verified. | -| DOCS-AIRGAP-57-001 | TODO | Docs Guild, AirGap Time Guild | AIRGAP-TIME-58-001 | Write `/docs/airgap/staleness-and-time.md` explaining time anchors, drift policies, staleness budgets, and UI indicators. | Doc merged; math checked; banner included. | -| DOCS-AIRGAP-57-002 | TODO | Docs Guild, Console Guild | CONSOLE-AIRGAP-57-001 | Publish `/docs/console/airgap.md` covering sealed badge, import wizard, staleness dashboards. | Doc merged; screenshots captured; banner present. | -| DOCS-AIRGAP-57-003 | TODO | Docs Guild, CLI Guild | CLI-AIRGAP-57-001 | Publish `/docs/cli/airgap.md` documenting commands, examples, exit codes. | Doc merged; examples validated; banner present. | -| DOCS-AIRGAP-57-004 | TODO | Docs Guild, Ops Guild | DEVOPS-AIRGAP-56-002 | Create `/docs/airgap/operations.md` with runbooks for imports, failure recovery, and auditing. | Doc merged; runbooks rehearsed; banner included. | -| DOCS-AIRGAP-58-001 | TODO | Docs Guild, Product Guild | CONSOLE-AIRGAP-58-002 | Provide `/docs/airgap/degradation-matrix.md` enumerating feature availability, fallbacks, remediation. | Doc merged; matrix reviewed; banner included. | -| DOCS-AIRGAP-58-002 | TODO | Docs Guild, Security Guild | PROV-OBS-54-001 | Update `/docs/security/trust-and-signing.md` with DSSE/TUF roots, rotation, and signed time tokens. | Doc merged; security sign-off recorded; banner present. | -| DOCS-AIRGAP-58-003 | TODO | Docs Guild, DevEx Guild | AIRGAP-POL-56-001 | Publish `/docs/dev/airgap-contracts.md` describing EgressPolicy usage, sealed-mode tests, linting. | Doc merged; sample code validated; banner included. | -| DOCS-AIRGAP-58-004 | TODO | Docs Guild, Evidence Locker Guild | EVID-OBS-55-001 | Document `/docs/airgap/portable-evidence.md` for exporting/importing portable evidence bundles across enclaves. | Doc merged; verification steps tested; banner present. | - -## SDKs & OpenAPI (Epic 17) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-OAS-61-001 | TODO | Docs Guild, API Contracts Guild | OAS-61-002 | Publish `/docs/api/overview.md` covering auth, tenancy, pagination, idempotency, rate limits with banner. | Doc merged; examples validated; banner present. | -| DOCS-OAS-61-002 | TODO | Docs Guild, API Governance Guild | APIGOV-61-001 | Author `/docs/api/conventions.md` capturing naming, errors, filters, sorting, examples. | Doc merged; lint passes; banner included. | -| DOCS-OAS-61-003 | TODO | Docs Guild, API Governance Guild | APIGOV-63-001 | Publish `/docs/api/versioning.md` describing SemVer, deprecation headers, migration playbooks. | Doc merged; example headers validated; banner present. | -| DOCS-OAS-62-001 | TODO | Docs Guild, Developer Portal Guild | DEVPORT-62-002 | Stand up `/docs/api/reference/` auto-generated site; integrate with portal nav. | Reference site builds; search works; banner included. | -| DOCS-SDK-62-001 | TODO | Docs Guild, SDK Generator Guild | SDKGEN-63-001 | Publish `/docs/sdks/overview.md` plus language guides (`typescript.md`, `python.md`, `go.md`, `java.md`). | Docs merged; code samples pulled from tested examples; banner present. | -| DOCS-DEVPORT-62-001 | TODO | Docs Guild, Developer Portal Guild | DEVPORT-62-001 | Document `/docs/devportal/publishing.md` for build pipeline, offline bundle steps. | Doc merged; cross-links validated; banner included. | -| DOCS-CONTRIB-62-001 | TODO | Docs Guild, API Governance Guild | APIGOV-61-001 | Publish `/docs/contributing/api-contracts.md` detailing how to edit OAS, lint rules, compatibility checks. | Doc merged; banner present; examples validated. | -| DOCS-TEST-62-001 | TODO | Docs Guild, Contract Testing Guild | CONTR-62-001 | Author `/docs/testing/contract-testing.md` covering mock server, replay tests, golden fixtures. | Doc merged; references to tooling validated; banner present. | -| DOCS-SEC-62-001 | TODO | Docs Guild, Authority Core | AUTH-AIRGAP-56-001 | Update `/docs/security/auth-scopes.md` with OAuth2/PAT scopes, tenancy header usage. | Doc merged; scope tables verified; banner included. | -| DOCS-AIRGAP-DEVPORT-64-001 | TODO | Docs Guild, DevPortal Offline Guild | DVOFF-64-001 | Create `/docs/airgap/devportal-offline.md` describing offline bundle usage and verification. | Doc merged; verification steps tested; banner present. | - -## Risk Profiles (Epic 18) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-RISK-66-001 | TODO | Docs Guild, Risk Profile Schema Guild | POLICY-RISK-66-001 | Publish `/docs/risk/overview.md` covering concepts and glossary. | Doc merged with banner; terminology reviewed. | -| DOCS-RISK-66-002 | TODO | Docs Guild, Policy Guild | POLICY-RISK-66-003 | Author `/docs/risk/profiles.md` (authoring, versioning, scope). | Doc merged; schema examples validated; banner present. | -| DOCS-RISK-66-003 | TODO | Docs Guild, Risk Engine Guild | RISK-ENGINE-67-001 | Publish `/docs/risk/factors.md` cataloging signals, transforms, reducers, TTLs. | Document merged; tables verified; banner included. | -| DOCS-RISK-66-004 | TODO | Docs Guild, Risk Engine Guild | RISK-ENGINE-66-002 | Create `/docs/risk/formulas.md` detailing math, normalization, gating, severity. | Doc merged; equations rendered; banner present. | -| DOCS-RISK-67-001 | TODO | Docs Guild, Risk Engine Guild | RISK-ENGINE-68-001 | Publish `/docs/risk/explainability.md` showing artifact schema and UI screenshots. | Doc merged; CLI examples validated; banner included. | -| DOCS-RISK-67-002 | TODO | Docs Guild, API Guild | POLICY-RISK-67-002 | Produce `/docs/risk/api.md` with endpoint reference/examples. | Doc merged; OAS examples synced; banner present. | -| DOCS-RISK-67-003 | TODO | Docs Guild, Console Guild | CONSOLE-RISK-66-001 | Document `/docs/console/risk-ui.md` for authoring, simulation, dashboards. | Doc merged; screenshots updated; banner included. | -| DOCS-RISK-67-004 | TODO | Docs Guild, CLI Guild | CLI-RISK-66-001 | Publish `/docs/cli/risk.md` covering CLI workflows. | Doc merged; command examples validated; banner present. | -| DOCS-RISK-68-001 | TODO | Docs Guild, Export Guild | RISK-BUNDLE-69-001 | Add `/docs/airgap/risk-bundles.md` for offline factor bundles. | Doc merged; verification steps confirmed; banner included. | -| DOCS-RISK-68-002 | TODO | Docs Guild, Security Guild | POLICY-RISK-66-003 | Update `/docs/security/aoc-invariants.md` with risk scoring provenance guarantees. | Doc merged; audit references updated; banner present. | - -## Attestor Console (Epic 19) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-ATTEST-73-001 | TODO | Docs Guild, Attestor Service Guild | ATTEST-TYPES-73-001 | Publish `/docs/attestor/overview.md` with imposed rule banner. | Doc merged; terminology validated. | -| DOCS-ATTEST-73-002 | TODO | Docs Guild, Attestation Payloads Guild | ATTEST-TYPES-73-002 | Write `/docs/attestor/payloads.md` with schemas/examples. | Doc merged; examples validated via tests. | -| DOCS-ATTEST-73-003 | TODO | Docs Guild, Policy Guild | POLICY-ATTEST-73-002 | Publish `/docs/attestor/policies.md` covering verification policies. | Doc merged; policy examples validated. | -| DOCS-ATTEST-73-004 | TODO | Docs Guild, Attestor Service Guild | ATTESTOR-73-002 | Add `/docs/attestor/workflows.md` detailing ingest, verify, bulk operations. | Doc merged; workflows tested. | -| DOCS-ATTEST-74-001 | TODO | Docs Guild, KMS Guild | KMS-73-001 | Publish `/docs/attestor/keys-and-issuers.md`. | Doc merged; rotation guidance verified. | -| DOCS-ATTEST-74-002 | TODO | Docs Guild, Transparency Guild | TRANSP-74-001 | Document `/docs/attestor/transparency.md` with witness usage/offline validation. | Doc merged; proofs validated. | -| DOCS-ATTEST-74-003 | TODO | Docs Guild, Attestor Console Guild | CONSOLE-ATTEST-73-001 | Write `/docs/console/attestor-ui.md` with screenshots/workflows. | Doc merged; screenshots captured; banner present. | -| DOCS-ATTEST-74-004 | TODO | Docs Guild, CLI Attestor Guild | CLI-ATTEST-73-001 | Publish `/docs/cli/attest.md` covering CLI usage. | Doc merged; commands validated. | -| DOCS-ATTEST-75-001 | TODO | Docs Guild, Export Attestation Guild | EXPORT-ATTEST-75-002 | Add `/docs/attestor/airgap.md` for attestation bundles. | Doc merged; verification steps confirmed. | -| DOCS-ATTEST-75-002 | TODO | Docs Guild, Security Guild | ATTESTOR-73-002 | Update `/docs/security/aoc-invariants.md` with attestation invariants. | Doc merged; invariants detailed. | -## Policy Engine v2 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-POLICY-20-001 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-ENGINE-20-000 | Author `/docs/policy/overview.md` covering concepts, inputs/outputs, determinism, and compliance checklist. | Doc published with diagrams + glossary; lint passes; checklist included. | -| DOCS-POLICY-20-002 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-ENGINE-20-001 | Write `/docs/policy/dsl.md` with grammar, built-ins, examples, anti-patterns. | DSL doc includes grammar tables, examples, compliance checklist; validated against parser tests. | -| DOCS-POLICY-20-003 | DONE (2025-10-26) | Docs Guild, Authority Core | AUTH-POLICY-20-001 | Publish `/docs/policy/lifecycle.md` describing draft→approve workflow, roles, audit, compliance list. | Lifecycle doc linked from UI/CLI help; approvals roles documented; checklist appended. | -| DOCS-POLICY-20-004 | DONE (2025-10-26) | Docs Guild, Scheduler Guild | SCHED-MODELS-20-001 | Create `/docs/policy/runs.md` detailing run modes, incremental mechanics, cursors, replay. | Run doc includes sequence diagrams + compliance checklist; cross-links to scheduler docs. | -| DOCS-POLICY-20-005 | DONE (2025-10-26) | Docs Guild, BE-Base Platform Guild | WEB-POLICY-20-001 | Draft `/docs/api/policy.md` describing endpoints, schemas, error codes. | API doc validated against OpenAPI; examples included; checklist appended. | -| DOCS-POLICY-20-006 | DONE (2025-10-26) | Docs Guild, DevEx/CLI Guild | CLI-POLICY-20-002 | Produce `/docs/cli/policy.md` with command usage, exit codes, JSON output contracts. | CLI doc includes examples, exit codes, compliance checklist. | -| DOCS-POLICY-20-007 | DONE (2025-10-26) | Docs Guild, UI Guild | UI-POLICY-20-001 | Document `/docs/ui/policy-editor.md` covering editor, simulation, diff workflows, approvals. | UI doc includes screenshots/placeholders, accessibility notes, compliance checklist. | -| DOCS-POLICY-20-008 | DONE (2025-10-26) | Docs Guild, Architecture Guild | POLICY-ENGINE-20-003 | Write `/docs/architecture/policy-engine.md` (new epic content) with sequence diagrams, selection strategy, schema. | Architecture doc merged with diagrams; compliance checklist appended; references updated. | -| DOCS-POLICY-20-009 | DONE (2025-10-26) | Docs Guild, Observability Guild | POLICY-ENGINE-20-007 | Add `/docs/observability/policy.md` for metrics/traces/logs, sample dashboards. | Observability doc includes metrics tables, dashboard screenshots, checklist. | -| DOCS-POLICY-20-010 | DONE (2025-10-26) | Docs Guild, Security Guild | AUTH-POLICY-20-002 | Publish `/docs/security/policy-governance.md` covering scopes, approvals, tenancy, least privilege. | Security doc merged; compliance checklist appended; reviewed by Security Guild. | -| DOCS-POLICY-20-011 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-ENGINE-20-001 | Populate `/docs/examples/policies/` with baseline/serverless/internal-only samples and commentary. | Example policies committed with explanations; lint passes; compliance checklist per file. | -| DOCS-POLICY-20-012 | DONE (2025-10-26) | Docs Guild, Support Guild | WEB-POLICY-20-003 | Draft `/docs/faq/policy-faq.md` addressing common pitfalls, VEX conflicts, determinism issues. | FAQ published with Q/A entries, cross-links, compliance checklist. | - -## Graph Explorer v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| - -## Link-Not-Merge v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-LNM-22-001 | BLOCKED (2025-10-27) | Docs Guild, Concelier Guild | CONCELIER-LNM-21-001..003 | Author `/docs/advisories/aggregation.md` covering observation vs linkset, conflict handling, AOC requirements, and reviewer checklist. | Draft doc merged with examples + checklist; final sign-off blocked until Concelier schema/API tasks land. | -> Blocker (2025-10-27): `CONCELIER-LNM-21-001..003` still TODO; update doc + fixtures once schema/API implementations are available. -| DOCS-LNM-22-002 | BLOCKED (2025-10-27) | Docs Guild, Excititor Guild | EXCITITOR-LNM-21-001..003 | Publish `/docs/vex/aggregation.md` describing VEX observation/linkset model, product matching, conflicts. | Draft doc merged with fixtures; final approval blocked until Excititor observation/linkset work ships. | -> Blocker (2025-10-27): `EXCITITOR-LNM-21-001..003` remain TODO; refresh doc, fixtures, and examples post-implementation. -| DOCS-LNM-22-003 | BLOCKED (2025-10-27) | Docs Guild, BE-Base Platform Guild | WEB-LNM-21-001..003 | Update `/docs/api/advisories.md` and `/docs/api/vex.md` for new endpoints, parameters, errors, exports. | Draft pending gateway/API delivery; unblock once endpoints + OpenAPI specs are available. | -> Blocker (2025-10-27): `WEB-LNM-21-001..003` all TODO—no gateway endpoints/OpenAPI to document yet. -| DOCS-LNM-22-004 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-40-001 | Create `/docs/policy/effective-severity.md` detailing severity selection strategies from multiple sources. | Doc merged with policy examples; checklist included. | -| DOCS-LNM-22-005 | BLOCKED (2025-10-27) | Docs Guild, UI Guild | UI-LNM-22-001..003 | Document `/docs/ui/evidence-panel.md` with screenshots, conflict badges, accessibility guidance. | Awaiting UI implementation to capture screenshots + flows; unblock once Evidence panel ships. | -> Blocker (2025-10-27): `UI-LNM-22-001..003` all TODO; documentation requires final UI states and accessibility audit artifacts. - -## StellaOps Console (Sprint 23) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-CONSOLE-23-001 | DONE (2025-10-26) | Docs Guild, Console Guild | CONSOLE-CORE-23-004 | Publish `/docs/ui/console-overview.md` covering IA, tenant model, global filters, and AOC alignment with compliance checklist. | Doc merged with diagrams + overview tables; checklist appended; Console Guild sign-off. | -| DOCS-CONSOLE-23-002 | DONE (2025-10-26) | Docs Guild, Console Guild | DOCS-CONSOLE-23-001 | Author `/docs/ui/navigation.md` detailing routes, breadcrumbs, keyboard shortcuts, deep links, and tenant context switching. | Navigation doc merged with shortcut tables and screenshots; accessibility checklist satisfied. | -| DOCS-CONSOLE-23-003 | DONE (2025-10-26) | Docs Guild, SBOM Service Guild, Console Guild | SBOM-CONSOLE-23-001, CONSOLE-FEAT-23-102 | Document `/docs/ui/sbom-explorer.md` (catalog, detail, graph overlays, exports) including compliance checklist and performance tips. | Doc merged with annotated screenshots, export instructions, and overlay examples; checklist appended. | -| DOCS-CONSOLE-23-004 | DONE (2025-10-26) | Docs Guild, Concelier Guild, Excititor Guild | CONCELIER-CONSOLE-23-001, EXCITITOR-CONSOLE-23-001 | Produce `/docs/ui/advisories-and-vex.md` explaining aggregation-not-merge, conflict indicators, raw viewers, and provenance banners. | Doc merged; raw JSON examples included; compliance checklist complete. | -| DOCS-CONSOLE-23-005 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-CONSOLE-23-001, CONSOLE-FEAT-23-104 | Write `/docs/ui/findings.md` describing filters, saved views, explain drawer, exports, and CLI parity callouts. | Doc merged with filter matrix + explain walkthrough; checklist appended. | -| DOCS-CONSOLE-23-006 | DONE (2025-10-26) | Docs Guild, Policy Guild, Product Ops | POLICY-CONSOLE-23-002, CONSOLE-FEAT-23-105 | Publish `/docs/ui/policies.md` with editor, simulation, approvals, compliance checklist, and RBAC mapping. | Doc merged; Monaco screenshots + simulation diff examples included; approval flow described; checklist appended. | -| DOCS-CONSOLE-23-007 | DONE (2025-10-26) | Docs Guild, Scheduler Guild | SCHED-CONSOLE-23-001, CONSOLE-FEAT-23-106 | Document `/docs/ui/runs.md` covering queues, live progress, diffs, retries, evidence downloads, and troubleshooting. | Doc merged with SSE troubleshooting, metrics references, compliance checklist. | -| DOCS-CONSOLE-23-008 | DONE (2025-10-26) | Docs Guild, Authority Guild | AUTH-CONSOLE-23-002, CONSOLE-FEAT-23-108 | Draft `/docs/ui/admin.md` describing users/roles, tenants, tokens, integrations, fresh-auth prompts, and RBAC mapping. | Doc merged with tables for scopes vs roles, screenshots, compliance checklist. | -| DOCS-CONSOLE-23-009 | DONE (2025-10-27) | Docs Guild, DevOps Guild | DOWNLOADS-CONSOLE-23-001, CONSOLE-FEAT-23-109 | Publish `/docs/ui/downloads.md` listing product images, commands, offline instructions, parity with CLI, and compliance checklist. | Doc merged; manifest sample included; copy-to-clipboard guidance documented; checklist complete. | -| DOCS-CONSOLE-23-010 | DONE (2025-10-27) | Docs Guild, Deployment Guild, Console Guild | DEVOPS-CONSOLE-23-002, CONSOLE-REL-23-301 | Write `/docs/deploy/console.md` (Helm, ingress, TLS, CSP, env vars, health checks) with compliance checklist. | Deploy doc merged; templates validated; CSP guidance included; checklist appended. | -| DOCS-CONSOLE-23-011 | DONE (2025-10-28) | Docs Guild, Deployment Guild | DOCS-CONSOLE-23-010 | Update `/docs/install/docker.md` to cover Console image, Compose/Helm usage, offline tarballs, parity with CLI. | Doc updated with new sections; commands validated; compliance checklist appended. | -| DOCS-CONSOLE-23-012 | DONE (2025-10-28) | Docs Guild, Security Guild | AUTH-CONSOLE-23-003, WEB-CONSOLE-23-002 | Publish `/docs/security/console-security.md` detailing OIDC flows, scopes, CSP, fresh-auth, evidence handling, and compliance checklist. | Security doc merged; threat model notes included; checklist appended. | -| DOCS-CONSOLE-23-013 | DONE (2025-10-28) | Docs Guild, Observability Guild | TELEMETRY-CONSOLE-23-001, CONSOLE-QA-23-403 | Write `/docs/observability/ui-telemetry.md` cataloguing metrics/logs/traces, dashboards, alerts, and feature flags. | Doc merged with instrumentation tables, dashboard screenshots, checklist appended. | -| DOCS-CONSOLE-23-014 | DONE (2025-10-28) | Docs Guild, Console Guild, CLI Guild | CONSOLE-DOC-23-502 | Maintain `/docs/cli-vs-ui-parity.md` matrix and integrate CI check guidance. | Matrix published with parity status, CI workflow documented, compliance checklist appended. | -> 2025-10-28: Install Docker guide references pending CLI commands (`stella downloads manifest`, `stella downloads mirror`, `stella console status`). Update once CLI parity lands. -| DOCS-CONSOLE-23-015 | DONE (2025-10-27) | Docs Guild, Architecture Guild | CONSOLE-CORE-23-001, WEB-CONSOLE-23-001 | Produce `/docs/architecture/console.md` describing frontend packages, data flow diagrams, SSE design, performance budgets. | Architecture doc merged with diagrams + compliance checklist; reviewers approve. | -| DOCS-CONSOLE-23-016 | DONE (2025-10-28) | Docs Guild, Accessibility Guild | CONSOLE-QA-23-402, CONSOLE-FEAT-23-102 | Refresh `/docs/accessibility.md` with Console-specific keyboard flows, color tokens, testing tools, and compliance checklist updates. | Accessibility doc updated; audits referenced; checklist appended. | -> 2025-10-28: Added guide covering keyboard matrix, screen reader behaviour, colour/focus tokens, testing workflow, offline guidance, and compliance checklist. -| DOCS-CONSOLE-23-017 | DONE (2025-10-27) | Docs Guild, Console Guild | CONSOLE-FEAT-23-101..109 | Create `/docs/examples/ui-tours.md` providing triage, audit, policy rollout walkthroughs with annotated screenshots and GIFs. | UI tours doc merged; capture instructions + asset placeholders committed; compliance checklist appended. | -| DOCS-CONSOLE-23-018 | DONE (2025-10-27) | Docs Guild, Security Guild | DOCS-CONSOLE-23-012 | Execute console security compliance checklist and capture Security Guild sign-off in Sprint 23 log. | Checklist completed; findings addressed or tickets filed; sign-off noted in updates file. | -| DOCS-LNM-22-006 | DONE (2025-10-27) | Docs Guild, Architecture Guild | CONCELIER-LNM-21-001..005, EXCITITOR-LNM-21-001..005 | Refresh `/docs/architecture/conseiller.md` and `/docs/architecture/excitator.md` describing observation/linkset pipelines and event contracts. | Architecture docs updated with observation/linkset flow + event tables; revisit once service implementations land. | -> Follow-up: align diagrams/examples after `CONCELIER-LNM-21` & `EXCITITOR-LNM-21` work merges (currently TODO). -| DOCS-LNM-22-007 | TODO | Docs Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005, DEVOPS-LNM-22-002 | Publish `/docs/observability/aggregation.md` with metrics/traces/logs/SLOs. | Observability doc merged; dashboards referenced; checklist appended. | -| DOCS-LNM-22-008 | TODO | Docs Guild, DevOps Guild | MERGE-LNM-21-001, CONCELIER-LNM-21-102 | Write `/docs/migration/no-merge.md` describing migration plan, backfill steps, rollback, feature flags. | Migration doc approved by stakeholders; checklist appended. | - -## Policy Engine + Editor v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-POLICY-23-001 | TODO | Docs Guild, Policy Guild | POLICY-SPL-23-001..003 | Author `/docs/policy/overview.md` describing SPL philosophy, layering, and glossary with reviewer checklist. | Doc merged; lint passes; checklist appended. | -| DOCS-POLICY-23-002 | TODO | Docs Guild, Policy Guild | POLICY-SPL-23-001 | Write `/docs/policy/spl-v1.md` (language reference, JSON Schema, examples). | Reference published with schema snippets; checklist completed. | -| DOCS-POLICY-23-003 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-50-001..004 | Produce `/docs/policy/runtime.md` covering compiler, evaluator, caching, events, SLOs. | Runtime doc merged with diagrams; observability references included. | -| DOCS-POLICY-23-004 | TODO | Docs Guild, UI Guild | UI-POLICY-23-001..006 | Document `/docs/policy/editor.md` (UI walkthrough, validation, simulation, approvals). | Editor doc merged with screenshots; accessibility checklist satisfied. | -| DOCS-POLICY-23-005 | TODO | Docs Guild, Security Guild | AUTH-POLICY-23-001..002 | Publish `/docs/policy/governance.md` (roles, scopes, approvals, signing, exceptions). | Governance doc merged; checklist appended. | -| DOCS-POLICY-23-006 | TODO | Docs Guild, BE-Base Platform Guild | WEB-POLICY-23-001..004 | Update `/docs/api/policy.md` with new endpoints, schemas, errors, pagination. | API doc aligns with OpenAPI; examples validated; checklist included. | -| DOCS-POLICY-23-007 | TODO | Docs Guild, DevEx/CLI Guild | CLI-POLICY-23-004..006 | Update `/docs/cli/policy.md` for lint/simulate/activate/history commands, exit codes. | CLI doc updated; samples verified; checklist appended. | -| DOCS-POLICY-23-008 | TODO | Docs Guild, Architecture Guild | POLICY-ENGINE-50-005..006 | Refresh `/docs/architecture/policy-engine.md` with data model, sequence diagrams, event flows. | Architecture doc merged with diagrams; checklist appended. | -| DOCS-POLICY-23-009 | TODO | Docs Guild, DevOps Guild | MERGE-LNM-21-001, DEVOPS-LNM-22-001 | Create `/docs/migration/policy-parity.md` covering dual-run parity plan and rollback. | Migration doc approved; checklist appended. | -| DOCS-POLICY-23-010 | TODO | Docs Guild, UI Guild | UI-POLICY-23-006 | Write `/docs/ui/explainers.md` showing explain trees, evidence overlays, interpretation guidance. | Doc merged with annotated screenshots; checklist appended. | - -## Graph & Vuln Explorer v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-GRAPH-24-001 | TODO | Docs Guild, UI Guild | UI-GRAPH-24-001..006 | Author `/docs/ui/sbom-graph-explorer.md` detailing overlays, filters, saved views, accessibility, and AOC visibility. | Doc merged; screenshots included; checklist appended. | -| DOCS-GRAPH-24-002 | TODO | Docs Guild, UI Guild | UI-GRAPH-24-005 | Publish `/docs/ui/vulnerability-explorer.md` covering table usage, grouping, fix suggestions, Why drawer. | Doc merged with annotated images; accessibility checklist satisfied. | -| DOCS-GRAPH-24-003 | TODO | Docs Guild, SBOM Service Guild | SBOM-GRAPH-24-001..003 | Create `/docs/architecture/graph-index.md` describing data model, ingestion pipeline, caches, events. | Architecture doc merged with diagrams; checklist appended. | -| DOCS-GRAPH-24-004 | TODO | Docs Guild, BE-Base Platform Guild | WEB-GRAPH-24-001..003 | Document `/docs/api/graph.md` and `/docs/api/vuln.md` avec endpoints, parameters, errors, RBAC. | API docs aligned with OpenAPI; examples validated; checklist appended. | -| DOCS-GRAPH-24-005 | TODO | Docs Guild, DevEx/CLI Guild | CLI-GRAPH-24-001..003 | Update `/docs/cli/graph-and-vuln.md` covering new CLI commands, exit codes, scripting. | CLI doc merged; examples tested; checklist appended. | -| DOCS-GRAPH-24-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-60-001..002 | Write `/docs/policy/ui-integration.md` explaining overlays, cache usage, simulator contracts. | Doc merged; references cross-linked; checklist appended. | -| DOCS-GRAPH-24-007 | TODO | Docs Guild, DevOps Guild | DEVOPS-GRAPH-24-001..003 | Produce `/docs/migration/graph-parity.md` with rollout plan, parity checks, fallback guidance. | Migration doc approved; checklist appended. | - -## Exceptions v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-EXC-25-001 | TODO | Docs Guild, Governance Guild | WEB-EXC-25-001 | Author `/docs/governance/exceptions.md` covering lifecycle, scope patterns, examples, compliance checklist. | Doc merged; reviewers sign off; checklist included. | -| DOCS-EXC-25-002 | TODO | Docs Guild, Authority Core | AUTH-EXC-25-001 | Publish `/docs/governance/approvals-and-routing.md` detailing roles, routing matrix, MFA rules, audit trails. | Doc merged; routing examples validated; checklist appended. | -| DOCS-EXC-25-003 | TODO | Docs Guild, BE-Base Platform Guild | WEB-EXC-25-001..003 | Create `/docs/api/exceptions.md` with endpoints, payloads, errors, idempotency notes. | API doc aligned with OpenAPI; examples tested; checklist appended. | -| DOCS-EXC-25-004 | DONE (2025-10-27) | Docs Guild, Policy Guild | POLICY-ENGINE-70-001 | Document `/docs/policy/exception-effects.md` explaining evaluation order, conflicts, simulation. | Doc merged; tests cross-referenced; checklist appended. | -| DOCS-EXC-25-005 | TODO | Docs Guild, UI Guild | UI-EXC-25-001..004 | Write `/docs/ui/exception-center.md` with UI walkthrough, badges, accessibility, shortcuts. | Doc merged with screenshots; accessibility checklist completed. | -| DOCS-EXC-25-006 | TODO | Docs Guild, DevEx/CLI Guild | CLI-EXC-25-001..002 | Update `/docs/cli/exceptions.md` covering command usage and exit codes. | CLI doc updated; examples validated; checklist appended. | -| DOCS-EXC-25-007 | TODO | Docs Guild, DevOps Guild | SCHED-WORKER-25-101, DEVOPS-GRAPH-24-003 | Publish `/docs/migration/exception-governance.md` describing cutover from legacy suppressions, notifications, rollback. | Migration doc approved; checklist included. | - -> Update statuses (TODO/DOING/REVIEW/DONE/BLOCKED) as progress changes. Keep guides in sync with configuration samples under `etc/`. - -> Remark (2025-10-13, DOC4.AUTH-PDG): Rate limit guide published (`docs/security/rate-limits.md`) and handed to plugin docs team for diagram uplift once PLG6.DIAGRAM lands. - -## Orchestrator Dashboard (Epic 9) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-ORCH-32-001 | TODO | Docs Guild | ORCH-SVC-32-001, AUTH-ORCH-32-001 | Author `/docs/orchestrator/overview.md` covering mission, roles, AOC alignment, governance, with imposed rule reminder. | Doc merged with diagrams; imposed rule statement included; entry linked from docs index. | -| DOCS-ORCH-32-002 | TODO | Docs Guild | ORCH-SVC-32-002 | Author `/docs/orchestrator/architecture.md` detailing scheduler, DAGs, rate limits, data model, message bus, storage layout, restating imposed rule. | Architecture doc merged; diagrams reviewed; imposed rule noted. | -| DOCS-ORCH-33-001 | TODO | Docs Guild | ORCH-SVC-33-001..004, WEB-ORCH-33-001 | Publish `/docs/orchestrator/api.md` (REST/WebSocket endpoints, payloads, error codes) with imposed rule note. | API doc merged; examples validated; imposed rule appended. | -| DOCS-ORCH-33-002 | TODO | Docs Guild | CONSOLE-ORCH-32-002, CONSOLE-ORCH-33-001..002 | Publish `/docs/orchestrator/console.md` covering screens, a11y, live updates, control actions, reiterating imposed rule. | Console doc merged with screenshots; accessibility checklist done; imposed rule statement present. | -| DOCS-ORCH-33-003 | TODO | Docs Guild | CLI-ORCH-33-001 | Publish `/docs/orchestrator/cli.md` documenting commands, options, exit codes, streaming output, offline usage, and imposed rule. | CLI doc merged; examples tested; imposed rule appended. | -| DOCS-ORCH-34-001 | TODO | Docs Guild | ORCH-SVC-34-002, LEDGER-34-101 | Author `/docs/orchestrator/run-ledger.md` covering ledger schema, provenance chain, audit workflows, with imposed rule reminder. | Run-ledger doc merged; payload samples validated; imposed rule included; cross-links added. | -| DOCS-ORCH-34-002 | TODO | Docs Guild | AUTH-ORCH-32-001, AUTH-ORCH-34-001 | Update `/docs/security/secrets-handling.md` for orchestrator KMS refs, redaction badges, operator hygiene, reiterating imposed rule. | Security doc merged; checklists updated; imposed rule restated; references from Console/CLI docs added. | -| DOCS-ORCH-34-003 | TODO | Docs Guild | ORCH-SVC-33-003, ORCH-SVC-34-001, DEVOPS-ORCH-34-001 | Publish `/docs/operations/orchestrator-runbook.md` (incident playbook, backfill guide, circuit breakers, throttling) with imposed rule statement. | Runbook merged; steps validated with DevOps; imposed rule included; runbook linked from ops index. | -| DOCS-ORCH-34-004 | TODO | Docs Guild | ORCH-SVC-32-005, WORKER-GO-33-001, WORKER-PY-33-001 | Document `/docs/schemas/artifacts.md` describing artifact kinds, schema versions, hashing, storage layout, restating imposed rule. | Schema doc merged; JSON schema provided; imposed rule included; sample payload validated. | -| DOCS-ORCH-34-005 | TODO | Docs Guild | ORCH-SVC-34-001, DEVOPS-ORCH-34-001 | Author `/docs/slo/orchestrator-slo.md` defining SLOs, burn alerts, measurement, and reiterating imposed rule. | SLO doc merged; dashboard screenshots embedded; imposed rule appended; alerts documented. | - -## Export Center (Epic 10) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-EXPORT-35-001 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-001..006 | Author `/docs/export-center/overview.md` covering purpose, profiles, security, AOC alignment, surfaces, ending with imposed rule statement. | Doc merged with diagrams/examples; imposed rule line present; index updated. | -| DOCS-EXPORT-35-002 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-002..005 | Publish `/docs/export-center/architecture.md` describing planner, adapters, manifests, signing, distribution flows, restating imposed rule. | Architecture doc merged; sequence diagrams included; rule statement appended. | -| DOCS-EXPORT-35-003 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-003..004 | Publish `/docs/export-center/profiles.md` detailing schema fields, examples, compatibility, and imposed rule reminder. | Profiles doc merged; JSON schemas linked; imposed rule noted. | -| DOCS-EXPORT-36-004 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-36-001..004, WEB-EXPORT-36-001 | Publish `/docs/export-center/api.md` covering endpoints, payloads, errors, and mention imposed rule. | API doc merged; examples validated; rule included. | -| DOCS-EXPORT-36-005 | DONE (2025-10-29) | Docs Guild | CLI-EXPORT-35-001, CLI-EXPORT-36-001 | Publish `/docs/export-center/cli.md` with command reference, CI scripts, verification steps, restating imposed rule. | CLI doc merged; script snippets tested; rule appended. | -| DOCS-EXPORT-36-006 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-36-001, DEVOPS-EXPORT-36-001 | Publish `/docs/export-center/trivy-adapter.md` covering field mappings, compatibility matrix, and imposed rule reminder. | Doc merged; mapping tables validated; rule included. | -| DOCS-EXPORT-37-001 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-37-001, DEVOPS-EXPORT-37-001 | Publish `/docs/export-center/mirror-bundles.md` describing filesystem/OCI layouts, delta/encryption, import guide, ending with imposed rule. | Doc merged; diagrams provided; verification steps tested; rule stated. | -| DOCS-EXPORT-37-002 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-005, EXPORT-SVC-37-002 | Publish `/docs/export-center/provenance-and-signing.md` detailing manifests, attestation flow, verification, reiterating imposed rule. | Doc merged; signature examples validated; rule appended. | -| DOCS-EXPORT-37-003 | DONE (2025-10-29) | Docs Guild | DEVOPS-EXPORT-37-001 | Publish `/docs/operations/export-runbook.md` covering failures, tuning, capacity planning, with imposed rule reminder. | Runbook merged; procedures validated; rule included. | -| DOCS-EXPORT-37-004 | TODO | Docs Guild | AUTH-EXPORT-37-001, EXPORT-SVC-37-002 | Publish `/docs/security/export-hardening.md` outlining RBAC, tenancy, encryption, redaction, restating imposed rule. | Security doc merged; checklist updated; rule appended. | -| DOCS-EXPORT-37-101 | TODO | Docs Guild, DevEx/CLI Guild | CLI-EXPORT-37-001 | Refresh CLI verification sections once `stella export verify` lands (flags, exit codes, samples). | `docs/export-center/cli.md` & `docs/export-center/provenance-and-signing.md` updated with final command syntax; examples tested; rule reminder retained. | -| DOCS-EXPORT-37-102 | TODO | Docs Guild, DevOps Guild | DEVOPS-EXPORT-37-001 | Embed export dashboards/alerts references into provenance/runbook docs after Grafana work ships. | Docs updated with dashboard IDs/alert notes; update logged; rule reminder present. | -| DOCS-EXPORT-37-005 | TODO | Docs Guild, Exporter Service Guild | EXPORT-SVC-35-006, DEVOPS-EXPORT-36-001 | Validate Export Center docs against live Trivy/mirror bundles once implementation lands; refresh examples and CLI snippets accordingly. | Real bundle examples recorded; docs updated; verification steps confirmed with production artefacts. | -> Note (2025-10-29): Blocked until exporter API (`EXPORT-SVC-35-006`) and Trivy/mirror adapters (`EXPORT-SVC-36-001`, `EXPORT-SVC-37-001`) ship. Requires access to CI smoke outputs (`DEVOPS-EXPORT-36-001`) for verification artifacts. - -## Reachability v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-SIG-26-001 | TODO | Docs Guild, Signals Guild | SIGNALS-24-004 | Write `/docs/signals/reachability.md` covering states, scores, provenance, retention. | Doc merged with diagrams/examples; checklist appended. | -| DOCS-SIG-26-002 | TODO | Docs Guild, Signals Guild | SIGNALS-24-002 | Publish `/docs/signals/callgraph-formats.md` with schemas and validation errors. | Doc merged; examples tested; checklist included. | -| DOCS-SIG-26-003 | TODO | Docs Guild, Runtime Guild | SIGNALS-24-003 | Create `/docs/signals/runtime-facts.md` detailing agent capabilities, privacy safeguards, opt-in flags. | Doc merged; privacy review done; checklist appended. | -| DOCS-SIG-26-004 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-80-001 | Document `/docs/policy/signals-weighting.md` for SPL predicates and weighting strategies. | Doc merged; sample policies validated; checklist appended. | -| DOCS-SIG-26-005 | TODO | Docs Guild, UI Guild | UI-SIG-26-001..003 | Draft `/docs/ui/reachability-overlays.md` with badges, timelines, shortcuts. | Doc merged with screenshots; accessibility checklist completed. | -| DOCS-SIG-26-006 | TODO | Docs Guild, DevEx/CLI Guild | CLI-SIG-26-001..002 | Update `/docs/cli/reachability.md` for new commands and automation recipes. | Doc merged; examples verified; checklist appended. | -| DOCS-SIG-26-007 | TODO | Docs Guild, BE-Base Platform Guild | WEB-SIG-26-001..003 | Publish `/docs/api/signals.md` covering endpoints, payloads, ETags, errors. | API doc aligned with OpenAPI; examples tested; checklist appended. | -| DOCS-SIG-26-008 | TODO | Docs Guild, DevOps Guild | DEVOPS-SIG-26-001..002 | Write `/docs/migration/enable-reachability.md` guiding rollout, fallbacks, monitoring. | Migration doc approved; checklist appended. | - -## Policy Studio (Sprint 27) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-POLICY-27-001 | BLOCKED (2025-10-27) | Docs Guild, Policy Guild | REGISTRY-API-27-001, POLICY-ENGINE-27-001 | Publish `/docs/policy/studio-overview.md` covering lifecycle, roles, glossary, and compliance checklist. | Doc merged with diagrams + lifecycle table; checklist appended; stakeholders sign off. | -> Blocked by `REGISTRY-API-27-001` and `POLICY-ENGINE-27-001`; need spec + compile data. -> Blocker: Registry OpenAPI (`REGISTRY-API-27-001`) and policy compile enrichments (`POLICY-ENGINE-27-001`) are still TODO; need final interfaces before drafting overview. -| DOCS-POLICY-27-002 | BLOCKED (2025-10-27) | Docs Guild, Console Guild | CONSOLE-STUDIO-27-001 | Write `/docs/policy/authoring.md` detailing workspace templates, snippets, lint rules, IDE shortcuts, and best practices. | Authoring doc includes annotated screenshots, snippet catalog, compliance checklist. | -> Blocked by `CONSOLE-STUDIO-27-001` Studio authoring UI pending. -> Blocker: Console Studio authoring UI (`CONSOLE-STUDIO-27-001`) not implemented; awaiting UX to capture flows/snippets. -| DOCS-POLICY-27-003 | BLOCKED (2025-10-27) | Docs Guild, Policy Registry Guild | REGISTRY-API-27-007 | Document `/docs/policy/versioning-and-publishing.md` (semver rules, attestations, rollback) with compliance checklist. | Doc merged with flow diagrams; attestation steps documented; checklist appended. | -> Blocked by `REGISTRY-API-27-007` publish/sign pipeline outstanding. -> Blocker: Registry publish/sign workflow (`REGISTRY-API-27-007`) pending. -| DOCS-POLICY-27-004 | BLOCKED (2025-10-27) | Docs Guild, Scheduler Guild | REGISTRY-API-27-005, SCHED-WORKER-27-301 | Write `/docs/policy/simulation.md` covering quick vs batch sim, thresholds, evidence bundles, CLI examples. | Simulation doc includes charts, sample manifests, checklist appended. | -> Blocked by `REGISTRY-API-27-005`/`SCHED-WORKER-27-301` batch simulation not ready. -> Blocker: Batch simulation APIs/workers (`REGISTRY-API-27-005`, `SCHED-WORKER-27-301`) still TODO. -| DOCS-POLICY-27-005 | BLOCKED (2025-10-27) | Docs Guild, Product Ops | REGISTRY-API-27-006 | Publish `/docs/policy/review-and-approval.md` with approver requirements, comments, webhooks, audit trail guidance. | Doc merged with role matrix + webhook schema; checklist appended. | -> Blocked by `REGISTRY-API-27-006` review workflow not implemented. -> Blocker: Review workflow (`REGISTRY-API-27-006`) not landed. -| DOCS-POLICY-27-006 | BLOCKED (2025-10-27) | Docs Guild, Policy Guild | REGISTRY-API-27-008 | Author `/docs/policy/promotion.md` covering environments, canary, rollback, and monitoring steps. | Promotion doc includes examples + checklist; verified by Policy Ops. | -> Blocked by `REGISTRY-API-27-008` promotion APIs pending. -> Blocker: Promotion/canary APIs (`REGISTRY-API-27-008`) outstanding. -| DOCS-POLICY-27-007 | BLOCKED (2025-10-27) | Docs Guild, DevEx/CLI Guild | CLI-POLICY-27-001..004 | Update `/docs/policy/cli.md` with new commands, JSON schemas, CI usage, and compliance checklist. | CLI doc merged with transcripts; schema references validated; checklist appended. | -> Blocked by `CLI-POLICY-27-001..004` CLI commands missing. -> Blocker: Policy CLI commands (`CLI-POLICY-27-001..004`) yet to implement. -| DOCS-POLICY-27-008 | BLOCKED (2025-10-27) | Docs Guild, Policy Registry Guild | REGISTRY-API-27-001..008 | Publish `/docs/policy/api.md` describing Registry endpoints, request/response schemas, errors, and feature flags. | API doc aligned with OpenAPI; examples validated; checklist appended. | -> Blocked by `REGISTRY-API-27-001..008` OpenAPI + endpoints incomplete. -> Blocker: Registry OpenAPI/spec suite (`REGISTRY-API-27-001..008`) incomplete. -| DOCS-POLICY-27-009 | BLOCKED (2025-10-27) | Docs Guild, Security Guild | AUTH-POLICY-27-002 | Create `/docs/security/policy-attestations.md` covering signing, verification, key rotation, and compliance checklist. | Security doc approved by Security Guild; verifier steps documented; checklist appended. | -> Blocked by `AUTH-POLICY-27-002` signing enforcement pending. -> Blocker: Authority signing enforcement (`AUTH-POLICY-27-002`) pending. -| DOCS-POLICY-27-010 | BLOCKED (2025-10-27) | Docs Guild, Architecture Guild | REGISTRY-API-27-001, SCHED-WORKER-27-301 | Author `/docs/architecture/policy-registry.md` (service design, schemas, queues, failure modes) with diagrams and checklist. | Architecture doc merged; diagrams committed; checklist appended. | -> Blocked by `REGISTRY-API-27-001` & `SCHED-WORKER-27-301` need delivery. -> Blocker: Policy Registry schema/workers not delivered (see `REGISTRY-API-27-001`, `SCHED-WORKER-27-301`). -| DOCS-POLICY-27-011 | BLOCKED (2025-10-27) | Docs Guild, Observability Guild | DEVOPS-POLICY-27-004 | Publish `/docs/observability/policy-telemetry.md` with metrics/log tables, dashboards, alerts, and compliance checklist. | Observability doc merged; dashboards linked; checklist appended. | -> Blocked by `DEVOPS-POLICY-27-004` observability dashboards outstanding. -> Blocker: Observability dashboards (`DEVOPS-POLICY-27-004`) not built. -| DOCS-POLICY-27-012 | BLOCKED (2025-10-27) | Docs Guild, Ops Guild | DEPLOY-POLICY-27-002 | Write `/docs/runbooks/policy-incident.md` detailing rollback, freeze, forensic steps, notifications. | Runbook merged; rehearsal recorded; checklist appended. | -> Blocked by `DEPLOY-POLICY-27-002` incident runbook inputs pending. -> Blocker: Ops runbook inputs (`DEPLOY-POLICY-27-002`) pending. -| DOCS-POLICY-27-013 | BLOCKED (2025-10-27) | Docs Guild, Policy Guild | CONSOLE-STUDIO-27-001, REGISTRY-API-27-002 | Update `/docs/examples/policy-templates.md` with new templates, snippets, and sample policies. | Examples committed with commentary; lint passes; checklist appended. | -> Blocked by `CONSOLE-STUDIO-27-001`/`REGISTRY-API-27-002` templates missing. -> Blocker: Studio templates and registry storage (`CONSOLE-STUDIO-27-001`, `REGISTRY-API-27-002`) not available. -| DOCS-POLICY-27-014 | BLOCKED (2025-10-27) | Docs Guild, Policy Registry Guild | REGISTRY-API-27-003, WEB-POLICY-27-001 | Refresh `/docs/aoc/aoc-guardrails.md` to include Studio-specific guardrails and validation scenarios. | Doc updated with Studio guardrails; compliance checklist appended. | -> Blocked by `REGISTRY-API-27-003` & `WEB-POLICY-27-001` guardrails not implemented. -> Blocker: Registry compile pipeline/web proxy (`REGISTRY-API-27-003`, `WEB-POLICY-27-001`) outstanding. - -## Vulnerability Explorer (Sprint 29) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-VULN-29-001 | TODO | Docs Guild, Vuln Explorer Guild | VULN-API-29-001 | Publish `/docs/vuln/explorer-overview.md` covering domain model, identities, AOC guarantees, workflow summary. | Doc merged with diagrams/table; compliance checklist appended. | -| DOCS-VULN-29-002 | TODO | Docs Guild, Console Guild | CONSOLE-VULN-29-001..006 | Write `/docs/vuln/explorer-using-console.md` with workflows, screenshots, keyboard shortcuts, saved views, deep links. | Doc merged; images stored; WCAG notes included; checklist appended. | -| DOCS-VULN-29-003 | TODO | Docs Guild, Vuln Explorer API Guild | VULN-API-29-001..009 | Author `/docs/vuln/explorer-api.md` (endpoints, query schema, grouping, errors, rate limits). | Doc aligned with OpenAPI; examples validated; checklist appended. | -| DOCS-VULN-29-004 | TODO | Docs Guild, DevEx/CLI Guild | CLI-VULN-29-001..005 | Publish `/docs/vuln/explorer-cli.md` with command reference, samples, exit codes, CI snippets. | CLI doc merged; transcripts/JSON outputs validated; checklist appended. | -| DOCS-VULN-29-005 | TODO | Docs Guild, Findings Ledger Guild | LEDGER-29-001..009 | Write `/docs/vuln/findings-ledger.md` detailing event schema, hashing, Merkle roots, replay tooling. | Doc merged; compliance checklist appended; audit team sign-off. | -| DOCS-VULN-29-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-29-001..003 | Update `/docs/policy/vuln-determinations.md` for new rationale, signals, simulation semantics. | Doc updated; examples validated; checklist appended. | -| DOCS-VULN-29-007 | TODO | Docs Guild, Excititor Guild | EXCITITOR-VULN-29-001..004 | Publish `/docs/vex/explorer-integration.md` covering CSAF mapping, suppression precedence, status semantics. | Doc merged; compliance checklist appended. | -| DOCS-VULN-29-008 | TODO | Docs Guild, Concelier Guild | CONCELIER-VULN-29-001..004 | Publish `/docs/advisories/explorer-integration.md` covering key normalization, withdrawn handling, provenance. | Doc merged; checklist appended. | -| DOCS-VULN-29-009 | TODO | Docs Guild, SBOM Service Guild | SBOM-VULN-29-001..002 | Author `/docs/sbom/vuln-resolution.md` detailing version semantics, scope, paths, safe version hints. | Doc merged; ecosystem tables validated; checklist appended. | -| DOCS-VULN-29-010 | TODO | Docs Guild, Observability Guild | VULN-API-29-009, DEVOPS-VULN-29-002 | Publish `/docs/observability/vuln-telemetry.md` (metrics, logs, tracing, dashboards, SLOs). | Doc merged; dashboards linked; checklist appended. | -| DOCS-VULN-29-011 | TODO | Docs Guild, Security Guild | AUTH-VULN-29-001..003 | Create `/docs/security/vuln-rbac.md` for roles, ABAC policies, attachment encryption, CSRF. | Security doc approved; checklist appended. | -| DOCS-VULN-29-012 | TODO | Docs Guild, Ops Guild | DEVOPS-VULN-29-002, SCHED-WORKER-29-003 | Write `/docs/runbooks/vuln-ops.md` (projector lag, resolver storms, export failures, policy activation). | Runbook merged; rehearsal recorded; checklist appended. | -| DOCS-VULN-29-013 | TODO | Docs Guild, Deployment Guild | DEPLOY-VULN-29-001..002 | Update `/docs/install/containers.md` with Findings Ledger & Vuln Explorer API images, manifests, resource sizing, health checks. | Install doc updated; validation commands included; checklist appended. | - -## VEX Lens (Sprint 30) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-VEX-30-001 | TODO | Docs Guild, VEX Lens Guild | VEXLENS-30-005 | Publish `/docs/vex/consensus-overview.md` describing purpose, scope, AOC guarantees. | Doc merged with diagrams/terminology tables; compliance checklist appended. | -| DOCS-VEX-30-002 | TODO | Docs Guild, VEX Lens Guild | VEXLENS-30-005 | Author `/docs/vex/consensus-algorithm.md` covering normalization, weighting, thresholds, examples. | Doc merged; math reviewed by Policy; checklist appended. | -| DOCS-VEX-30-003 | TODO | Docs Guild, Issuer Directory Guild | ISSUER-30-001..003 | Document `/docs/vex/issuer-directory.md` (issuer management, keys, trust overrides, audit). | Doc merged; security review done; checklist appended. | -| DOCS-VEX-30-004 | TODO | Docs Guild, VEX Lens Guild | VEXLENS-30-007 | Publish `/docs/vex/consensus-api.md` with endpoint specs, query params, rate limits. | API doc aligned with OpenAPI; examples validated; checklist appended. | -| DOCS-VEX-30-005 | TODO | Docs Guild, Console Guild | CONSOLE-VEX-30-001 | Write `/docs/vex/consensus-console.md` covering UI workflows, filters, conflicts, accessibility. | Doc merged; screenshots added; checklist appended. | -| DOCS-VEX-30-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-29-001, VEXLENS-30-004 | Add `/docs/policy/vex-trust-model.md` detailing policy knobs, thresholds, simulation. | Doc merged; policy review completed; checklist appended. | -| DOCS-VEX-30-007 | TODO | Docs Guild, SBOM Service Guild | VEXLENS-30-002 | Publish `/docs/sbom/vex-mapping.md` (CPE→purl strategy, edge cases, overrides). | Doc merged; mapping tables validated; checklist appended. | -| DOCS-VEX-30-008 | TODO | Docs Guild, Security Guild | ISSUER-30-002, VEXLENS-30-003 | Deliver `/docs/security/vex-signatures.md` (verification flow, key rotation, audit). | Doc approved by Security; checklist appended. | -| DOCS-VEX-30-009 | TODO | Docs Guild, DevOps Guild | VEXLENS-30-009, DEVOPS-VEX-30-001 | Create `/docs/runbooks/vex-ops.md` for recompute storms, mapping failures, signature errors. | Runbook merged; rehearsal logged; checklist appended. | - -## Advisory AI (Sprint 31) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-AIAI-31-001 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-006 | Publish `/docs/advisory-ai/overview.md` covering capabilities, guardrails, RBAC. | Doc merged with diagrams; compliance checklist appended. | -| DOCS-AIAI-31-002 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-004 | Author `/docs/advisory-ai/architecture.md` detailing RAG pipeline, deterministics, caching, model options. | Doc merged; architecture review done; checklist appended. | -| DOCS-AIAI-31-003 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-006 | Write `/docs/advisory-ai/api.md` describing endpoints, schemas, errors, rate limits. | API doc aligned with OpenAPI; examples validated; checklist appended. | -| DOCS-AIAI-31-004 | TODO | Docs Guild, Console Guild | CONSOLE-VULN-29-001, CONSOLE-VEX-30-001 | Create `/docs/advisory-ai/console.md` with screenshots, a11y notes, copy-as-ticket instructions. | Doc merged; images stored; checklist appended. | -| DOCS-AIAI-31-005 | TODO | Docs Guild, DevEx/CLI Guild | CLI-VULN-29-001, CLI-VEX-30-001 | Publish `/docs/advisory-ai/cli.md` covering commands, exit codes, scripting patterns. | Doc merged; examples tested; checklist appended. | -| DOCS-AIAI-31-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-31-001 | Update `/docs/policy/assistant-parameters.md` covering temperature, token limits, ranking weights, TTLs. | Doc merged; policy review done; checklist appended. | -| DOCS-AIAI-31-007 | TODO | Docs Guild, Security Guild | AIAI-31-005 | Write `/docs/security/assistant-guardrails.md` detailing redaction, injection defense, logging. | Doc approved by Security; checklist appended. | -| DOCS-AIAI-31-008 | TODO | Docs Guild, SBOM Service Guild | SBOM-AIAI-31-001 | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). | Doc merged; heuristics reviewed; checklist appended. | -| DOCS-AIAI-31-009 | TODO | Docs Guild, DevOps Guild | DEVOPS-AIAI-31-001 | Create `/docs/runbooks/assistant-ops.md` for warmup, cache priming, model outages, scaling. | Runbook merged; rehearsal logged; checklist appended. | - -## Notifications Studio - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-NOTIFY-38-001 | DONE (2025-10-29) | Docs Guild, Notifications Service Guild | NOTIFY-SVC-38-001..004 | Publish `/docs/notifications/overview.md` and `/docs/notifications/architecture.md`, each ending with imposed rule reminder. | Docs merged; diagrams verified; imposed rule appended. | -| DOCS-NOTIFY-39-002 | DONE (2025-10-29) | Docs Guild, Notifications Service Guild | NOTIFY-SVC-39-001..004 | Publish `/docs/notifications/rules.md`, `/docs/notifications/templates.md`, `/docs/notifications/digests.md` with examples and imposed rule line. | Docs merged; examples validated; imposed rule appended. | -| DOCS-NOTIFY-40-001 | TODO | Docs Guild, Security Guild | AUTH-NOTIFY-38-001, NOTIFY-SVC-40-001..004 | Publish `/docs/notifications/channels.md`, `/docs/notifications/escalations.md`, `/docs/notifications/api.md`, `/docs/operations/notifier-runbook.md`, `/docs/security/notifications-hardening.md`; each ends with imposed rule line. | Docs merged; accessibility checks passed; imposed rule appended. | - -## CLI Parity & Task Packs - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-CLI-41-001 | TODO | Docs Guild, DevEx/CLI Guild | CLI-CORE-41-001 | Publish `/docs/cli/overview.md`, `/docs/cli/configuration.md`, `/docs/cli/output-and-exit-codes.md` with imposed rule statements. | Docs merged; examples verified; imposed rule appended. | -| DOCS-CLI-42-001 | TODO | Docs Guild | DOCS-CLI-41-001, CLI-PARITY-41-001 | Publish `/docs/cli/parity-matrix.md` and command guides under `/docs/cli/commands/*.md` (policy, sbom, vuln, vex, advisory, export, orchestrator, notify, aoc, auth). | Guides merged; parity automation documented; imposed rule appended. | -| DOCS-PACKS-43-001 | DONE (2025-10-27) | Docs Guild, Task Runner Guild | PACKS-REG-42-001, TASKRUN-42-001 | Publish `/docs/task-packs/spec.md`, `/docs/task-packs/authoring-guide.md`, `/docs/task-packs/registry.md`, `/docs/task-packs/runbook.md`, `/docs/security/pack-signing-and-rbac.md`, `/docs/operations/cli-release-and-packaging.md` with imposed rule statements. | Docs merged; tutorials validated; imposed rule appended; cross-links added. | - -## Containerized Distribution (Epic 13) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-INSTALL-44-001 | TODO | Docs Guild, Deployment Guild | COMPOSE-44-001 | Publish `/docs/install/overview.md` and `/docs/install/compose-quickstart.md` with imposed rule line and copy-ready commands. | Docs merged; screenshots/commands verified; imposed rule appended. | -| DOCS-INSTALL-45-001 | TODO | Docs Guild, Deployment Guild | HELM-45-001 | Publish `/docs/install/helm-prod.md` and `/docs/install/configuration-reference.md` with values tables and imposed rule reminder. | Docs merged; configuration matrix verified; imposed rule appended. | -| DOCS-INSTALL-46-001 | TODO | Docs Guild, Security Guild | DEPLOY-PACKS-43-001, CLI-PACKS-43-001 | Publish `/docs/install/airgap.md`, `/docs/security/supply-chain.md`, `/docs/operations/health-and-readiness.md`, `/docs/release/image-catalog.md`, `/docs/console/onboarding.md` (each with imposed rule). | Docs merged; checksum/signature sections validated; imposed rule appended. | - -## Authority-Backed Scopes & Tenancy (Epic 14) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCS-TEN-47-001 | TODO | Docs Guild, Authority Core | AUTH-TEN-47-001 | Publish `/docs/security/tenancy-overview.md` and `/docs/security/scopes-and-roles.md` outlining scope grammar, tenant model, imposed rule reminder. | Docs merged; diagrams included; imposed rule appended. | -| DOCS-TEN-48-001 | TODO | Docs Guild, Platform Ops | WEB-TEN-48-001 | Publish `/docs/operations/multi-tenancy.md`, `/docs/operations/rls-and-data-isolation.md`, `/docs/console/admin-tenants.md`. | Docs merged; examples validated; imposed rule appended. | -| DOCS-TEN-49-001 | TODO | Docs & DevEx Guilds | CLI-TEN-47-001, AUTH-TEN-49-001 | Publish `/docs/cli/authentication.md`, `/docs/api/authentication.md`, `/docs/policy/examples/abac-overlays.md`, update `/docs/install/configuration-reference.md` with new env vars, all ending with imposed rule line. | Docs merged; command examples verified; imposed rule appended. | +# Docs Guild Task Board (UTC 2025-10-10) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOC7.README-INDEX | DONE (2025-10-17) | Docs Guild | — | Refresh index docs (docs/README.md + root README) after architecture dossier split and Offline Kit overhaul. | ✅ ToC reflects new component architecture docs; ✅ root README highlights updated doc set; ✅ Offline Kit guide linked correctly. | +| DOC4.AUTH-PDG | DONE (2025-10-19) | Docs Guild, Plugin Team | PLG6.DOC | Copy-edit `docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md`, export lifecycle diagram, add LDAP RFC cross-link. | ✅ PR merged with polish; ✅ Diagram committed; ✅ Slack handoff posted. | +| DOC1.AUTH | DONE (2025-10-12) | Docs Guild, Authority Core | CORE5B.DOC | Draft `docs/11_AUTHORITY.md` covering architecture, configuration, bootstrap flows. | ✅ Architecture + config sections approved by Core; ✅ Samples reference latest options; ✅ Offline note added. | +| DOC3.Concelier-Authority | DONE (2025-10-12) | Docs Guild, DevEx | FSR4 | Polish operator/runbook sections (DOC3/DOC5) to document Concelier authority rollout, bypass logging, and enforcement checklist. | ✅ DOC3/DOC5 updated with audit runbook references; ✅ enforcement deadline highlighted; ✅ Docs guild sign-off. | +| DOC5.Concelier-Runbook | DONE (2025-10-12) | Docs Guild | DOC3.Concelier-Authority | Produce dedicated Concelier authority audit runbook covering log fields, monitoring recommendations, and troubleshooting steps. | ✅ Runbook published; ✅ linked from DOC3/DOC5; ✅ alerting guidance included. | +| FEEDDOCS-DOCS-05-001 | DONE (2025-10-11) | Docs Guild | FEEDMERGE-ENGINE-04-001, FEEDMERGE-ENGINE-04-002 | Publish Concelier conflict resolution runbook covering precedence workflow, merge-event auditing, and Sprint 3 metrics. | ✅ `docs/modules/concelier/operations/conflict-resolution.md` committed; ✅ metrics/log tables align with latest merge code; ✅ Ops alert guidance handed to Concelier team. | +| FEEDDOCS-DOCS-05-002 | DONE (2025-10-16) | Docs Guild, Concelier Ops | FEEDDOCS-DOCS-05-001 | Ops sign-off captured: conflict runbook circulated, alert thresholds tuned, and rollout decisions documented in change log. | ✅ Ops review recorded; ✅ alert thresholds finalised using `docs/modules/concelier/operations/authority-audit-runbook.md`; ✅ change-log entry linked from runbook once GHSA/NVD/OSV regression fixtures land. | +| DOCS-ADR-09-001 | DONE (2025-10-19) | Docs Guild, DevEx | — | Establish ADR process (`docs/adr/0000-template.md`) and document usage guidelines. | Template published; README snippet linking ADR process; announcement posted (`docs/updates/2025-10-18-docs-guild.md`). | +| DOCS-EVENTS-09-002 | DONE (2025-10-19) | Docs Guild, Platform Events | SCANNER-EVENTS-15-201 | Publish event schema catalog (`docs/events/`) for `scanner.report.ready@1`, `scheduler.rescan.delta@1`, `attestor.logged@1`. | Schemas validated (Ajv CI hooked); docs/events/README summarises usage; Platform Events notified via `docs/updates/2025-10-18-docs-guild.md`. | +| DOCS-EVENTS-09-003 | DONE (2025-10-19) | Docs Guild | DOCS-EVENTS-09-002 | Add human-readable envelope field references and canonical payload samples for published events, including offline validation workflow. | Tables explain common headers/payload segments; versioned sample payloads committed; README links to validation instructions and samples. | +| DOCS-EVENTS-09-004 | DONE (2025-10-19) | Docs Guild, Scanner WebService | SCANNER-EVENTS-15-201 | Refresh scanner event docs to mirror DSSE-backed report fields, document `scanner.scan.completed`, and capture canonical sample validation. | Schemas updated for new payload shape; README references DSSE reuse and validation test; samples align with emitted events. | +| PLATFORM-EVENTS-09-401 | DONE (2025-10-21) | Platform Events Guild | DOCS-EVENTS-09-003 | Embed canonical event samples into contract/integration tests and ensure CI validates payloads against published schemas. | Notify models tests now run schema validation against `docs/events/*.json`, event schemas allow optional `attributes`, and docs capture the new validation workflow. | +| RUNTIME-GUILD-09-402 | DONE (2025-10-19) | Runtime Guild | SCANNER-POLICY-09-107 | Confirm Scanner WebService surfaces `quietedFindingCount` and progress hints to runtime consumers; document readiness checklist. | Runtime verification run captures enriched payload; checklist/doc updates merged; stakeholders acknowledge availability. | +| DOCS-CONCELIER-07-201 | DONE (2025-10-22) | Docs Guild, Concelier WebService | FEEDWEB-DOCS-01-001 | Final editorial review and publish pass for Concelier authority toggle documentation (Quickstart + operator guide). | Review feedback resolved, publish PR merged, release notes updated with documentation pointer. | +| DOCS-RUNTIME-17-004 | DONE (2025-10-26) | Docs Guild, Runtime Guild | SCANNER-EMIT-17-701, ZASTAVA-OBS-17-005, DEVOPS-REL-17-002 | Document build-id workflows: SBOM exposure, runtime event payloads (`process.buildId`), Scanner `/policy/runtime` response (`buildIds` list), debug-store layout, and operator guidance for symbol retrieval. | Architecture + operator docs updated with build-id sections (Observer, Scanner, CLI), examples show `readelf` output + debuginfod usage, references linked from Offline Kit/Release guides + CLI help. | +| DOCS-OBS-50-001 | BLOCKED (2025-10-26) | Docs Guild, Observability Guild | TELEMETRY-OBS-50-001 | Publish `/docs/observability/overview.md` introducing scope, imposed rule banner, architecture diagram, and tenant guarantees. | Doc merged with imposed rule banner; diagram committed; cross-links to telemetry stack + evidence locker docs. | +> Blocked: waiting on telemetry core deliverable (TELEMETRY-OBS-50-001) to finalise architecture details and diagrams. +| DOCS-OBS-50-002 | TODO | Docs Guild, Security Guild | TELEMETRY-OBS-50-002 | Author `/docs/observability/telemetry-standards.md` detailing common fields, scrubbing policy, sampling defaults, and redaction override procedure. | Doc merged; imposed rule banner present; examples validated with telemetry fixtures; security review sign-off captured. | +| DOCS-OBS-50-003 | TODO | Docs Guild, Observability Guild | TELEMETRY-OBS-50-001 | Create `/docs/observability/logging.md` covering structured log schema, dos/don'ts, tenant isolation, and copyable examples. | Doc merged with banner; sample logs redacted; lint passes; linked from coding standards. | +| DOCS-OBS-50-004 | TODO | Docs Guild, Observability Guild | TELEMETRY-OBS-50-002 | Draft `/docs/observability/tracing.md` explaining context propagation, async linking, CLI header usage, and sampling strategies. | Doc merged; imposed rule banner included; diagrams updated; references to CLI/Console features added. | +| DOCS-OBS-51-001 | TODO | Docs Guild, DevOps Guild | WEB-OBS-51-001, DEVOPS-OBS-51-001 | Publish `/docs/observability/metrics-and-slos.md` cataloging metrics, SLO targets, burn rate policies, and alert runbooks. | Doc merged with banner; SLO tables verified; alert workflows linked to incident runbook. | +| DOCS-SEC-OBS-50-001 | TODO | Docs Guild, Security Guild | TELEMETRY-OBS-51-002 | Update `/docs/security/redaction-and-privacy.md` to cover telemetry privacy controls, tenant opt-in debug, and imposed rule reminder. | Doc merged; redaction matrix updated; banner present; security sign-off recorded. | +| DOCS-INSTALL-50-001 | TODO | Docs Guild, DevOps Guild | DEVOPS-OBS-50-003 | Add `/docs/install/telemetry-stack.md` with collector deployment, exporter options, offline kit notes, and imposed rule banner. | Doc merged; install steps verified on air-gapped profile; banner present; screenshots attached. | +| DOCS-FORENSICS-53-001 | TODO | Docs Guild, Evidence Locker Guild | EVID-OBS-53-003 | Publish `/docs/forensics/evidence-locker.md` describing bundle formats, WORM options, retention, legal hold, and imposed rule banner. | Doc merged; manifest examples validated; banner present; legal hold steps aligned with API. | +| DOCS-FORENSICS-53-002 | TODO | Docs Guild, Provenance Guild | PROV-OBS-54-001 | Release `/docs/forensics/provenance-attestation.md` covering DSSE schema, signing process, verification workflow, and imposed rule banner. | Doc merged; sample statements reference fixtures; banner included; verification steps tested. | +| DOCS-FORENSICS-53-003 | TODO | Docs Guild, Timeline Indexer Guild | TIMELINE-OBS-52-003 | Publish `/docs/forensics/timeline.md` with schema, event kinds, filters, query examples, and imposed rule banner. | Doc merged; query examples validated; banner present; linked from Console/CLI docs. | +| DOCS-CONSOLE-OBS-52-001 | TODO | Docs Guild, Console Guild | CONSOLE-OBS-51-001 | Document `/docs/console/observability.md` showcasing Observability Hub widgets, trace/log search, imposed rule banner, and accessibility tips. | Doc merged; screenshots updated; banner present; navigation steps verified. | +| DOCS-CONSOLE-OBS-52-002 | TODO | Docs Guild, Console Guild | CONSOLE-OBS-52-002, CONSOLE-OBS-53-001 | Publish `/docs/console/forensics.md` covering timeline explorer, evidence viewer, attestation verifier, imposed rule banner, and troubleshooting. | Doc merged; banner included; workflows validated via Playwright capture; troubleshooting section populated. | +| DOCS-CLI-OBS-52-001 | TODO | Docs Guild, DevEx/CLI Guild | CLI-OBS-52-001 | Create `/docs/modules/cli/guides/observability.md` detailing `stella obs` commands, examples, exit codes, imposed rule banner, and scripting tips. | Doc merged; examples tested; banner included; CLI parity matrix updated. | +| DOCS-CLI-FORENSICS-53-001 | TODO | Docs Guild, DevEx/CLI Guild | CLI-FORENSICS-54-001 | Publish `/docs/modules/cli/guides/forensics.md` for snapshot/verify/attest commands with sample outputs, imposed rule banner, and offline workflows. | Doc merged; sample bundles verified; banner present; offline notes cross-linked. | +| DOCS-RUNBOOK-55-001 | TODO | Docs Guild, Ops Guild | DEVOPS-OBS-55-001, WEB-OBS-55-001 | Author `/docs/runbooks/incidents.md` describing incident mode activation, escalation steps, retention impact, verification checklist, and imposed rule banner. | Doc merged; runbook rehearsed; banner included; linked from alerts. | +| DOCS-AOC-19-001 | DONE (2025-10-26) | Docs Guild, Concelier Guild | CONCELIER-WEB-AOC-19-001, EXCITITOR-WEB-AOC-19-001 | Author `/docs/ingestion/aggregation-only-contract.md` covering philosophy, invariants, schemas, error codes, migration, observability, and security checklist. | New doc published with compliance checklist; cross-links from existing docs added. | +| DOCS-AOC-19-002 | DONE (2025-10-26) | Docs Guild, Architecture Guild | DOCS-AOC-19-001 | Update `/docs/modules/platform/architecture-overview.md` to include AOC boundary, raw stores, and sequence diagram (fetch → guard → raw insert → policy evaluation). | Overview doc updated with diagrams/text; lint passes; stakeholders sign off. | +| DOCS-AOC-19-003 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-AOC-19-003 | Refresh `/docs/modules/policy/architecture.md` clarifying ingestion boundary, raw inputs, and policy-only derived data. | Doc highlights raw-only ingestion contract, updated diagrams merge, compliance checklist added. | +| DOCS-AOC-19-004 | DONE (2025-10-26) | Docs Guild, UI Guild | UI-AOC-19-001 | Extend `/docs/ui/console.md` with Sources dashboard tiles, violation drill-down workflow, and verification action. | UI doc updated with screenshots/flow descriptions, compliance checklist appended. | +> DOCS-AOC-19-004: Architecture overview & policy-engine updates landed 2025-10-26; incorporate the new AOC boundary diagrams and metrics references. +| DOCS-AOC-19-005 | DONE (2025-10-26) | Docs Guild, CLI Guild | CLI-AOC-19-003 | Update `/docs/modules/cli/guides/cli-reference.md` with `stella sources ingest --dry-run` and `stella aoc verify` usage, exit codes, and offline notes. | CLI reference + quickstart sections updated; examples validated; compliance checklist added. | +> DOCS-AOC-19-005: New ingestion reference + architecture overview published 2025-10-26; ensure CLI docs link to both and surface AOC exit codes mapping. +| DOCS-AOC-19-006 | DONE (2025-10-26) | Docs Guild, Observability Guild | CONCELIER-WEB-AOC-19-002, EXCITITOR-WEB-AOC-19-002 | Document new metrics/traces/log keys in `/docs/observability/observability.md`. | Observability doc lists new metrics/traces/log fields; dashboards referenced; compliance checklist appended. | +| DOCS-AOC-19-007 | DONE (2025-10-26) | Docs Guild, Authority Core | AUTH-AOC-19-001 | Update `/docs/security/authority-scopes.md` with new ingestion scopes and tenancy enforcement notes. | Doc reflects new scopes, sample policies updated, compliance checklist added. | +| DOCS-AOC-19-008 | DONE (2025-10-26) | Docs Guild, DevOps Guild | DEVOPS-AOC-19-002 | Refresh `/docs/deploy/containers.md` to cover validator enablement, guard env flags, and read-only verify user. | Deploy doc updated; offline kit section mentions validator scripts; compliance checklist appended. | +| DOCS-AOC-19-009 | DONE (2025-10-26) | Docs Guild, Authority Core | AUTH-AOC-19-001 | Update AOC docs/samples to reflect new `advisory:*`, `vex:*`, and `aoc:verify` scopes. | Docs reference new scopes, samples aligned, compliance checklist updated. | + +## Air-Gapped Mode (Epic 16) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-AIRGAP-56-001 | TODO | Docs Guild, AirGap Controller Guild | AIRGAP-CTL-56-002 | Publish `/docs/airgap/overview.md` outlining modes, lifecycle, responsibilities, and imposed rule banner. | Doc merged; banner present; diagrams included. | +| DOCS-AIRGAP-56-002 | TODO | Docs Guild, DevOps Guild | DEVOPS-AIRGAP-56-001 | Author `/docs/airgap/sealing-and-egress.md` covering network policies, EgressPolicy facade usage, and verification steps. | Doc merged; examples validated; banner included. | +| DOCS-AIRGAP-56-003 | TODO | Docs Guild, Exporter Guild | EXPORT-AIRGAP-56-001 | Create `/docs/airgap/mirror-bundles.md` describing bundle format, DSSE/TUF/Merkle validation, creation/import workflows. | Doc merged; sample commands verified; banner present. | +| DOCS-AIRGAP-56-004 | TODO | Docs Guild, Deployment Guild | DEVOPS-AIRGAP-56-003 | Publish `/docs/airgap/bootstrap.md` detailing Bootstrap Pack creation, validation, and install procedures. | Doc merged; checklist appended; screenshots verified. | +| DOCS-AIRGAP-57-001 | TODO | Docs Guild, AirGap Time Guild | AIRGAP-TIME-58-001 | Write `/docs/airgap/staleness-and-time.md` explaining time anchors, drift policies, staleness budgets, and UI indicators. | Doc merged; math checked; banner included. | +| DOCS-AIRGAP-57-002 | TODO | Docs Guild, Console Guild | CONSOLE-AIRGAP-57-001 | Publish `/docs/console/airgap.md` covering sealed badge, import wizard, staleness dashboards. | Doc merged; screenshots captured; banner present. | +| DOCS-AIRGAP-57-003 | TODO | Docs Guild, CLI Guild | CLI-AIRGAP-57-001 | Publish `/docs/modules/cli/guides/airgap.md` documenting commands, examples, exit codes. | Doc merged; examples validated; banner present. | +| DOCS-AIRGAP-57-004 | TODO | Docs Guild, Ops Guild | DEVOPS-AIRGAP-56-002 | Create `/docs/airgap/operations.md` with runbooks for imports, failure recovery, and auditing. | Doc merged; runbooks rehearsed; banner included. | +| DOCS-AIRGAP-58-001 | TODO | Docs Guild, Product Guild | CONSOLE-AIRGAP-58-002 | Provide `/docs/airgap/degradation-matrix.md` enumerating feature availability, fallbacks, remediation. | Doc merged; matrix reviewed; banner included. | +| DOCS-AIRGAP-58-002 | TODO | Docs Guild, Security Guild | PROV-OBS-54-001 | Update `/docs/security/trust-and-signing.md` with DSSE/TUF roots, rotation, and signed time tokens. | Doc merged; security sign-off recorded; banner present. | +| DOCS-AIRGAP-58-003 | TODO | Docs Guild, DevEx Guild | AIRGAP-POL-56-001 | Publish `/docs/dev/airgap-contracts.md` describing EgressPolicy usage, sealed-mode tests, linting. | Doc merged; sample code validated; banner included. | +| DOCS-AIRGAP-58-004 | TODO | Docs Guild, Evidence Locker Guild | EVID-OBS-55-001 | Document `/docs/airgap/portable-evidence.md` for exporting/importing portable evidence bundles across enclaves. | Doc merged; verification steps tested; banner present. | + +## SDKs & OpenAPI (Epic 17) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-OAS-61-001 | TODO | Docs Guild, API Contracts Guild | OAS-61-002 | Publish `/docs/api/overview.md` covering auth, tenancy, pagination, idempotency, rate limits with banner. | Doc merged; examples validated; banner present. | +| DOCS-OAS-61-002 | TODO | Docs Guild, API Governance Guild | APIGOV-61-001 | Author `/docs/api/conventions.md` capturing naming, errors, filters, sorting, examples. | Doc merged; lint passes; banner included. | +| DOCS-OAS-61-003 | TODO | Docs Guild, API Governance Guild | APIGOV-63-001 | Publish `/docs/api/versioning.md` describing SemVer, deprecation headers, migration playbooks. | Doc merged; example headers validated; banner present. | +| DOCS-OAS-62-001 | TODO | Docs Guild, Developer Portal Guild | DEVPORT-62-002 | Stand up `/docs/api/reference/` auto-generated site; integrate with portal nav. | Reference site builds; search works; banner included. | +| DOCS-SDK-62-001 | TODO | Docs Guild, SDK Generator Guild | SDKGEN-63-001 | Publish `/docs/sdks/overview.md` plus language guides (`typescript.md`, `python.md`, `go.md`, `java.md`). | Docs merged; code samples pulled from tested examples; banner present. | +| DOCS-DEVPORT-62-001 | TODO | Docs Guild, Developer Portal Guild | DEVPORT-62-001 | Document `/docs/devportal/publishing.md` for build pipeline, offline bundle steps. | Doc merged; cross-links validated; banner included. | +| DOCS-CONTRIB-62-001 | TODO | Docs Guild, API Governance Guild | APIGOV-61-001 | Publish `/docs/contributing/api-contracts.md` detailing how to edit OAS, lint rules, compatibility checks. | Doc merged; banner present; examples validated. | +| DOCS-TEST-62-001 | TODO | Docs Guild, Contract Testing Guild | CONTR-62-001 | Author `/docs/testing/contract-testing.md` covering mock server, replay tests, golden fixtures. | Doc merged; references to tooling validated; banner present. | +| DOCS-SEC-62-001 | TODO | Docs Guild, Authority Core | AUTH-AIRGAP-56-001 | Update `/docs/security/auth-scopes.md` with OAuth2/PAT scopes, tenancy header usage. | Doc merged; scope tables verified; banner included. | +| DOCS-AIRGAP-DEVPORT-64-001 | TODO | Docs Guild, DevPortal Offline Guild | DVOFF-64-001 | Create `/docs/airgap/devportal-offline.md` describing offline bundle usage and verification. | Doc merged; verification steps tested; banner present. | + +## Risk Profiles (Epic 18) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-RISK-66-001 | TODO | Docs Guild, Risk Profile Schema Guild | POLICY-RISK-66-001 | Publish `/docs/risk/overview.md` covering concepts and glossary. | Doc merged with banner; terminology reviewed. | +| DOCS-RISK-66-002 | TODO | Docs Guild, Policy Guild | POLICY-RISK-66-003 | Author `/docs/risk/profiles.md` (authoring, versioning, scope). | Doc merged; schema examples validated; banner present. | +| DOCS-RISK-66-003 | TODO | Docs Guild, Risk Engine Guild | RISK-ENGINE-67-001 | Publish `/docs/risk/factors.md` cataloging signals, transforms, reducers, TTLs. | Document merged; tables verified; banner included. | +| DOCS-RISK-66-004 | TODO | Docs Guild, Risk Engine Guild | RISK-ENGINE-66-002 | Create `/docs/risk/formulas.md` detailing math, normalization, gating, severity. | Doc merged; equations rendered; banner present. | +| DOCS-RISK-67-001 | TODO | Docs Guild, Risk Engine Guild | RISK-ENGINE-68-001 | Publish `/docs/risk/explainability.md` showing artifact schema and UI screenshots. | Doc merged; CLI examples validated; banner included. | +| DOCS-RISK-67-002 | TODO | Docs Guild, API Guild | POLICY-RISK-67-002 | Produce `/docs/risk/api.md` with endpoint reference/examples. | Doc merged; OAS examples synced; banner present. | +| DOCS-RISK-67-003 | TODO | Docs Guild, Console Guild | CONSOLE-RISK-66-001 | Document `/docs/console/risk-ui.md` for authoring, simulation, dashboards. | Doc merged; screenshots updated; banner included. | +| DOCS-RISK-67-004 | TODO | Docs Guild, CLI Guild | CLI-RISK-66-001 | Publish `/docs/modules/cli/guides/risk.md` covering CLI workflows. | Doc merged; command examples validated; banner present. | +| DOCS-RISK-68-001 | TODO | Docs Guild, Export Guild | RISK-BUNDLE-69-001 | Add `/docs/airgap/risk-bundles.md` for offline factor bundles. | Doc merged; verification steps confirmed; banner included. | +| DOCS-RISK-68-002 | TODO | Docs Guild, Security Guild | POLICY-RISK-66-003 | Update `/docs/security/aoc-invariants.md` with risk scoring provenance guarantees. | Doc merged; audit references updated; banner present. | + +## Attestor Console (Epic 19) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-ATTEST-73-001 | TODO | Docs Guild, Attestor Service Guild | ATTEST-TYPES-73-001 | Publish `/docs/modules/attestor/overview.md` with imposed rule banner. | Doc merged; terminology validated. | +| DOCS-ATTEST-73-002 | TODO | Docs Guild, Attestation Payloads Guild | ATTEST-TYPES-73-002 | Write `/docs/modules/attestor/payloads.md` with schemas/examples. | Doc merged; examples validated via tests. | +| DOCS-ATTEST-73-003 | TODO | Docs Guild, Policy Guild | POLICY-ATTEST-73-002 | Publish `/docs/modules/attestor/policies.md` covering verification policies. | Doc merged; policy examples validated. | +| DOCS-ATTEST-73-004 | TODO | Docs Guild, Attestor Service Guild | ATTESTOR-73-002 | Add `/docs/modules/attestor/workflows.md` detailing ingest, verify, bulk operations. | Doc merged; workflows tested. | +| DOCS-ATTEST-74-001 | TODO | Docs Guild, KMS Guild | KMS-73-001 | Publish `/docs/modules/attestor/keys-and-issuers.md`. | Doc merged; rotation guidance verified. | +| DOCS-ATTEST-74-002 | TODO | Docs Guild, Transparency Guild | TRANSP-74-001 | Document `/docs/modules/attestor/transparency.md` with witness usage/offline validation. | Doc merged; proofs validated. | +| DOCS-ATTEST-74-003 | TODO | Docs Guild, Attestor Console Guild | CONSOLE-ATTEST-73-001 | Write `/docs/console/attestor-ui.md` with screenshots/workflows. | Doc merged; screenshots captured; banner present. | +| DOCS-ATTEST-74-004 | TODO | Docs Guild, CLI Attestor Guild | CLI-ATTEST-73-001 | Publish `/docs/modules/cli/guides/attest.md` covering CLI usage. | Doc merged; commands validated. | +| DOCS-ATTEST-75-001 | TODO | Docs Guild, Export Attestation Guild | EXPORT-ATTEST-75-002 | Add `/docs/modules/attestor/airgap.md` for attestation bundles. | Doc merged; verification steps confirmed. | +| DOCS-ATTEST-75-002 | TODO | Docs Guild, Security Guild | ATTESTOR-73-002 | Update `/docs/security/aoc-invariants.md` with attestation invariants. | Doc merged; invariants detailed. | +## Policy Engine v2 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-POLICY-20-001 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-ENGINE-20-000 | Author `/docs/policy/overview.md` covering concepts, inputs/outputs, determinism, and compliance checklist. | Doc published with diagrams + glossary; lint passes; checklist included. | +| DOCS-POLICY-20-002 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-ENGINE-20-001 | Write `/docs/policy/dsl.md` with grammar, built-ins, examples, anti-patterns. | DSL doc includes grammar tables, examples, compliance checklist; validated against parser tests. | +| DOCS-POLICY-20-003 | DONE (2025-10-26) | Docs Guild, Authority Core | AUTH-POLICY-20-001 | Publish `/docs/policy/lifecycle.md` describing draft→approve workflow, roles, audit, compliance list. | Lifecycle doc linked from UI/CLI help; approvals roles documented; checklist appended. | +| DOCS-POLICY-20-004 | DONE (2025-10-26) | Docs Guild, Scheduler Guild | SCHED-MODELS-20-001 | Create `/docs/policy/runs.md` detailing run modes, incremental mechanics, cursors, replay. | Run doc includes sequence diagrams + compliance checklist; cross-links to scheduler docs. | +| DOCS-POLICY-20-005 | DONE (2025-10-26) | Docs Guild, BE-Base Platform Guild | WEB-POLICY-20-001 | Draft `/docs/api/policy.md` describing endpoints, schemas, error codes. | API doc validated against OpenAPI; examples included; checklist appended. | +| DOCS-POLICY-20-006 | DONE (2025-10-26) | Docs Guild, DevEx/CLI Guild | CLI-POLICY-20-002 | Produce `/docs/modules/cli/guides/policy.md` with command usage, exit codes, JSON output contracts. | CLI doc includes examples, exit codes, compliance checklist. | +| DOCS-POLICY-20-007 | DONE (2025-10-26) | Docs Guild, UI Guild | UI-POLICY-20-001 | Document `/docs/ui/policy-editor.md` covering editor, simulation, diff workflows, approvals. | UI doc includes screenshots/placeholders, accessibility notes, compliance checklist. | +| DOCS-POLICY-20-008 | DONE (2025-10-26) | Docs Guild, Architecture Guild | POLICY-ENGINE-20-003 | Write `/docs/modules/policy/architecture.md` (new epic content) with sequence diagrams, selection strategy, schema. | Architecture doc merged with diagrams; compliance checklist appended; references updated. | +| DOCS-POLICY-20-009 | DONE (2025-10-26) | Docs Guild, Observability Guild | POLICY-ENGINE-20-007 | Add `/docs/observability/policy.md` for metrics/traces/logs, sample dashboards. | Observability doc includes metrics tables, dashboard screenshots, checklist. | +| DOCS-POLICY-20-010 | DONE (2025-10-26) | Docs Guild, Security Guild | AUTH-POLICY-20-002 | Publish `/docs/security/policy-governance.md` covering scopes, approvals, tenancy, least privilege. | Security doc merged; compliance checklist appended; reviewed by Security Guild. | +| DOCS-POLICY-20-011 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-ENGINE-20-001 | Populate `/docs/examples/policies/` with baseline/serverless/internal-only samples and commentary. | Example policies committed with explanations; lint passes; compliance checklist per file. | +| DOCS-POLICY-20-012 | DONE (2025-10-26) | Docs Guild, Support Guild | WEB-POLICY-20-003 | Draft `/docs/faq/policy-faq.md` addressing common pitfalls, VEX conflicts, determinism issues. | FAQ published with Q/A entries, cross-links, compliance checklist. | + +## Graph Explorer v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| + +## Link-Not-Merge v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-LNM-22-001 | BLOCKED (2025-10-27) | Docs Guild, Concelier Guild | CONCELIER-LNM-21-001..003 | Author `/docs/advisories/aggregation.md` covering observation vs linkset, conflict handling, AOC requirements, and reviewer checklist. | Draft doc merged with examples + checklist; final sign-off blocked until Concelier schema/API tasks land. | +> Blocker (2025-10-27): `CONCELIER-LNM-21-001..003` still TODO; update doc + fixtures once schema/API implementations are available. +| DOCS-LNM-22-002 | BLOCKED (2025-10-27) | Docs Guild, Excititor Guild | EXCITITOR-LNM-21-001..003 | Publish `/docs/vex/aggregation.md` describing VEX observation/linkset model, product matching, conflicts. | Draft doc merged with fixtures; final approval blocked until Excititor observation/linkset work ships. | +> Blocker (2025-10-27): `EXCITITOR-LNM-21-001..003` remain TODO; refresh doc, fixtures, and examples post-implementation. +| DOCS-LNM-22-003 | BLOCKED (2025-10-27) | Docs Guild, BE-Base Platform Guild | WEB-LNM-21-001..003 | Update `/docs/api/advisories.md` and `/docs/api/vex.md` for new endpoints, parameters, errors, exports. | Draft pending gateway/API delivery; unblock once endpoints + OpenAPI specs are available. | +> Blocker (2025-10-27): `WEB-LNM-21-001..003` all TODO—no gateway endpoints/OpenAPI to document yet. +| DOCS-LNM-22-004 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-40-001 | Create `/docs/policy/effective-severity.md` detailing severity selection strategies from multiple sources. | Doc merged with policy examples; checklist included. | +| DOCS-LNM-22-005 | BLOCKED (2025-10-27) | Docs Guild, UI Guild | UI-LNM-22-001..003 | Document `/docs/ui/evidence-panel.md` with screenshots, conflict badges, accessibility guidance. | Awaiting UI implementation to capture screenshots + flows; unblock once Evidence panel ships. | +> Blocker (2025-10-27): `UI-LNM-22-001..003` all TODO; documentation requires final UI states and accessibility audit artifacts. + +## StellaOps Console (Sprint 23) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-CONSOLE-23-001 | DONE (2025-10-26) | Docs Guild, Console Guild | CONSOLE-CORE-23-004 | Publish `/docs/ui/console-overview.md` covering IA, tenant model, global filters, and AOC alignment with compliance checklist. | Doc merged with diagrams + overview tables; checklist appended; Console Guild sign-off. | +| DOCS-CONSOLE-23-002 | DONE (2025-10-26) | Docs Guild, Console Guild | DOCS-CONSOLE-23-001 | Author `/docs/ui/navigation.md` detailing routes, breadcrumbs, keyboard shortcuts, deep links, and tenant context switching. | Navigation doc merged with shortcut tables and screenshots; accessibility checklist satisfied. | +| DOCS-CONSOLE-23-003 | DONE (2025-10-26) | Docs Guild, SBOM Service Guild, Console Guild | SBOM-CONSOLE-23-001, CONSOLE-FEAT-23-102 | Document `/docs/ui/sbom-explorer.md` (catalog, detail, graph overlays, exports) including compliance checklist and performance tips. | Doc merged with annotated screenshots, export instructions, and overlay examples; checklist appended. | +| DOCS-CONSOLE-23-004 | DONE (2025-10-26) | Docs Guild, Concelier Guild, Excititor Guild | CONCELIER-CONSOLE-23-001, EXCITITOR-CONSOLE-23-001 | Produce `/docs/ui/advisories-and-vex.md` explaining aggregation-not-merge, conflict indicators, raw viewers, and provenance banners. | Doc merged; raw JSON examples included; compliance checklist complete. | +| DOCS-CONSOLE-23-005 | DONE (2025-10-26) | Docs Guild, Policy Guild | POLICY-CONSOLE-23-001, CONSOLE-FEAT-23-104 | Write `/docs/ui/findings.md` describing filters, saved views, explain drawer, exports, and CLI parity callouts. | Doc merged with filter matrix + explain walkthrough; checklist appended. | +| DOCS-CONSOLE-23-006 | DONE (2025-10-26) | Docs Guild, Policy Guild, Product Ops | POLICY-CONSOLE-23-002, CONSOLE-FEAT-23-105 | Publish `/docs/ui/policies.md` with editor, simulation, approvals, compliance checklist, and RBAC mapping. | Doc merged; Monaco screenshots + simulation diff examples included; approval flow described; checklist appended. | +| DOCS-CONSOLE-23-007 | DONE (2025-10-26) | Docs Guild, Scheduler Guild | SCHED-CONSOLE-23-001, CONSOLE-FEAT-23-106 | Document `/docs/ui/runs.md` covering queues, live progress, diffs, retries, evidence downloads, and troubleshooting. | Doc merged with SSE troubleshooting, metrics references, compliance checklist. | +| DOCS-CONSOLE-23-008 | DONE (2025-10-26) | Docs Guild, Authority Guild | AUTH-CONSOLE-23-002, CONSOLE-FEAT-23-108 | Draft `/docs/ui/admin.md` describing users/roles, tenants, tokens, integrations, fresh-auth prompts, and RBAC mapping. | Doc merged with tables for scopes vs roles, screenshots, compliance checklist. | +| DOCS-CONSOLE-23-009 | DONE (2025-10-27) | Docs Guild, DevOps Guild | DOWNLOADS-CONSOLE-23-001, CONSOLE-FEAT-23-109 | Publish `/docs/ui/downloads.md` listing product images, commands, offline instructions, parity with CLI, and compliance checklist. | Doc merged; manifest sample included; copy-to-clipboard guidance documented; checklist complete. | +| DOCS-CONSOLE-23-010 | DONE (2025-10-27) | Docs Guild, Deployment Guild, Console Guild | DEVOPS-CONSOLE-23-002, CONSOLE-REL-23-301 | Write `/docs/deploy/console.md` (Helm, ingress, TLS, CSP, env vars, health checks) with compliance checklist. | Deploy doc merged; templates validated; CSP guidance included; checklist appended. | +| DOCS-CONSOLE-23-011 | DONE (2025-10-28) | Docs Guild, Deployment Guild | DOCS-CONSOLE-23-010 | Update `/docs/install/docker.md` to cover Console image, Compose/Helm usage, offline tarballs, parity with CLI. | Doc updated with new sections; commands validated; compliance checklist appended. | +| DOCS-CONSOLE-23-012 | DONE (2025-10-28) | Docs Guild, Security Guild | AUTH-CONSOLE-23-003, WEB-CONSOLE-23-002 | Publish `/docs/security/console-security.md` detailing OIDC flows, scopes, CSP, fresh-auth, evidence handling, and compliance checklist. | Security doc merged; threat model notes included; checklist appended. | +| DOCS-CONSOLE-23-013 | DONE (2025-10-28) | Docs Guild, Observability Guild | TELEMETRY-CONSOLE-23-001, CONSOLE-QA-23-403 | Write `/docs/observability/ui-telemetry.md` cataloguing metrics/logs/traces, dashboards, alerts, and feature flags. | Doc merged with instrumentation tables, dashboard screenshots, checklist appended. | +| DOCS-CONSOLE-23-014 | DONE (2025-10-28) | Docs Guild, Console Guild, CLI Guild | CONSOLE-DOC-23-502 | Maintain `/docs/cli-vs-ui-parity.md` matrix and integrate CI check guidance. | Matrix published with parity status, CI workflow documented, compliance checklist appended. | +> 2025-10-28: Install Docker guide references pending CLI commands (`stella downloads manifest`, `stella downloads mirror`, `stella console status`). Update once CLI parity lands. +| DOCS-CONSOLE-23-015 | DONE (2025-10-27) | Docs Guild, Architecture Guild | CONSOLE-CORE-23-001, WEB-CONSOLE-23-001 | Produce `/docs/modules/ui/console-architecture.md` describing frontend packages, data flow diagrams, SSE design, performance budgets. | Architecture doc merged with diagrams + compliance checklist; reviewers approve. | +| DOCS-CONSOLE-23-016 | DONE (2025-10-28) | Docs Guild, Accessibility Guild | CONSOLE-QA-23-402, CONSOLE-FEAT-23-102 | Refresh `/docs/accessibility.md` with Console-specific keyboard flows, color tokens, testing tools, and compliance checklist updates. | Accessibility doc updated; audits referenced; checklist appended. | +> 2025-10-28: Added guide covering keyboard matrix, screen reader behaviour, colour/focus tokens, testing workflow, offline guidance, and compliance checklist. +| DOCS-CONSOLE-23-017 | DONE (2025-10-27) | Docs Guild, Console Guild | CONSOLE-FEAT-23-101..109 | Create `/docs/examples/ui-tours.md` providing triage, audit, policy rollout walkthroughs with annotated screenshots and GIFs. | UI tours doc merged; capture instructions + asset placeholders committed; compliance checklist appended. | +| DOCS-CONSOLE-23-018 | DONE (2025-10-27) | Docs Guild, Security Guild | DOCS-CONSOLE-23-012 | Execute console security compliance checklist and capture Security Guild sign-off in Sprint 23 log. | Checklist completed; findings addressed or tickets filed; sign-off noted in updates file. | +| DOCS-LNM-22-006 | DONE (2025-10-27) | Docs Guild, Architecture Guild | CONCELIER-LNM-21-001..005, EXCITITOR-LNM-21-001..005 | Refresh `/docs/modules/concelier/architecture.md` and `/docs/modules/excititor/architecture.md` describing observation/linkset pipelines and event contracts. | Architecture docs updated with observation/linkset flow + event tables; revisit once service implementations land. | +> Follow-up: align diagrams/examples after `CONCELIER-LNM-21` & `EXCITITOR-LNM-21` work merges (currently TODO). +| DOCS-LNM-22-007 | TODO | Docs Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005, DEVOPS-LNM-22-002 | Publish `/docs/observability/aggregation.md` with metrics/traces/logs/SLOs. | Observability doc merged; dashboards referenced; checklist appended. | +| DOCS-LNM-22-008 | TODO | Docs Guild, DevOps Guild | MERGE-LNM-21-001, CONCELIER-LNM-21-102 | Write `/docs/migration/no-merge.md` describing migration plan, backfill steps, rollback, feature flags. | Migration doc approved by stakeholders; checklist appended. | + +## Policy Engine + Editor v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-POLICY-23-001 | TODO | Docs Guild, Policy Guild | POLICY-SPL-23-001..003 | Author `/docs/policy/overview.md` describing SPL philosophy, layering, and glossary with reviewer checklist. | Doc merged; lint passes; checklist appended. | +| DOCS-POLICY-23-002 | TODO | Docs Guild, Policy Guild | POLICY-SPL-23-001 | Write `/docs/policy/spl-v1.md` (language reference, JSON Schema, examples). | Reference published with schema snippets; checklist completed. | +| DOCS-POLICY-23-003 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-50-001..004 | Produce `/docs/policy/runtime.md` covering compiler, evaluator, caching, events, SLOs. | Runtime doc merged with diagrams; observability references included. | +| DOCS-POLICY-23-004 | TODO | Docs Guild, UI Guild | UI-POLICY-23-001..006 | Document `/docs/policy/editor.md` (UI walkthrough, validation, simulation, approvals). | Editor doc merged with screenshots; accessibility checklist satisfied. | +| DOCS-POLICY-23-005 | TODO | Docs Guild, Security Guild | AUTH-POLICY-23-001..002 | Publish `/docs/policy/governance.md` (roles, scopes, approvals, signing, exceptions). | Governance doc merged; checklist appended. | +| DOCS-POLICY-23-006 | TODO | Docs Guild, BE-Base Platform Guild | WEB-POLICY-23-001..004 | Update `/docs/api/policy.md` with new endpoints, schemas, errors, pagination. | API doc aligns with OpenAPI; examples validated; checklist included. | +| DOCS-POLICY-23-007 | TODO | Docs Guild, DevEx/CLI Guild | CLI-POLICY-23-004..006 | Update `/docs/modules/cli/guides/policy.md` for lint/simulate/activate/history commands, exit codes. | CLI doc updated; samples verified; checklist appended. | +| DOCS-POLICY-23-008 | TODO | Docs Guild, Architecture Guild | POLICY-ENGINE-50-005..006 | Refresh `/docs/modules/policy/architecture.md` with data model, sequence diagrams, event flows. | Architecture doc merged with diagrams; checklist appended. | +| DOCS-POLICY-23-009 | TODO | Docs Guild, DevOps Guild | MERGE-LNM-21-001, DEVOPS-LNM-22-001 | Create `/docs/migration/policy-parity.md` covering dual-run parity plan and rollback. | Migration doc approved; checklist appended. | +| DOCS-POLICY-23-010 | TODO | Docs Guild, UI Guild | UI-POLICY-23-006 | Write `/docs/ui/explainers.md` showing explain trees, evidence overlays, interpretation guidance. | Doc merged with annotated screenshots; checklist appended. | + +## Graph & Vuln Explorer v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-GRAPH-24-001 | TODO | Docs Guild, UI Guild | UI-GRAPH-24-001..006 | Author `/docs/ui/sbom-graph-explorer.md` detailing overlays, filters, saved views, accessibility, and AOC visibility. | Doc merged; screenshots included; checklist appended. | +| DOCS-GRAPH-24-002 | TODO | Docs Guild, UI Guild | UI-GRAPH-24-005 | Publish `/docs/ui/vulnerability-explorer.md` covering table usage, grouping, fix suggestions, Why drawer. | Doc merged with annotated images; accessibility checklist satisfied. | +| DOCS-GRAPH-24-003 | TODO | Docs Guild, SBOM Service Guild | SBOM-GRAPH-24-001..003 | Create `/docs/modules/graph/architecture-index.md` describing data model, ingestion pipeline, caches, events. | Architecture doc merged with diagrams; checklist appended. | +| DOCS-GRAPH-24-004 | TODO | Docs Guild, BE-Base Platform Guild | WEB-GRAPH-24-001..003 | Document `/docs/api/graph.md` and `/docs/api/vuln.md` avec endpoints, parameters, errors, RBAC. | API docs aligned with OpenAPI; examples validated; checklist appended. | +| DOCS-GRAPH-24-005 | TODO | Docs Guild, DevEx/CLI Guild | CLI-GRAPH-24-001..003 | Update `/docs/modules/cli/guides/graph-and-vuln.md` covering new CLI commands, exit codes, scripting. | CLI doc merged; examples tested; checklist appended. | +| DOCS-GRAPH-24-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-60-001..002 | Write `/docs/policy/ui-integration.md` explaining overlays, cache usage, simulator contracts. | Doc merged; references cross-linked; checklist appended. | +| DOCS-GRAPH-24-007 | TODO | Docs Guild, DevOps Guild | DEVOPS-GRAPH-24-001..003 | Produce `/docs/migration/graph-parity.md` with rollout plan, parity checks, fallback guidance. | Migration doc approved; checklist appended. | + +## Exceptions v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-EXC-25-001 | TODO | Docs Guild, Governance Guild | WEB-EXC-25-001 | Author `/docs/governance/exceptions.md` covering lifecycle, scope patterns, examples, compliance checklist. | Doc merged; reviewers sign off; checklist included. | +| DOCS-EXC-25-002 | TODO | Docs Guild, Authority Core | AUTH-EXC-25-001 | Publish `/docs/governance/approvals-and-routing.md` detailing roles, routing matrix, MFA rules, audit trails. | Doc merged; routing examples validated; checklist appended. | +| DOCS-EXC-25-003 | TODO | Docs Guild, BE-Base Platform Guild | WEB-EXC-25-001..003 | Create `/docs/api/exceptions.md` with endpoints, payloads, errors, idempotency notes. | API doc aligned with OpenAPI; examples tested; checklist appended. | +| DOCS-EXC-25-004 | DONE (2025-10-27) | Docs Guild, Policy Guild | POLICY-ENGINE-70-001 | Document `/docs/policy/exception-effects.md` explaining evaluation order, conflicts, simulation. | Doc merged; tests cross-referenced; checklist appended. | +| DOCS-EXC-25-005 | TODO | Docs Guild, UI Guild | UI-EXC-25-001..004 | Write `/docs/ui/exception-center.md` with UI walkthrough, badges, accessibility, shortcuts. | Doc merged with screenshots; accessibility checklist completed. | +| DOCS-EXC-25-006 | TODO | Docs Guild, DevEx/CLI Guild | CLI-EXC-25-001..002 | Update `/docs/modules/cli/guides/exceptions.md` covering command usage and exit codes. | CLI doc updated; examples validated; checklist appended. | +| DOCS-EXC-25-007 | TODO | Docs Guild, DevOps Guild | SCHED-WORKER-25-101, DEVOPS-GRAPH-24-003 | Publish `/docs/migration/exception-governance.md` describing cutover from legacy suppressions, notifications, rollback. | Migration doc approved; checklist included. | + +> Update statuses (TODO/DOING/REVIEW/DONE/BLOCKED) as progress changes. Keep guides in sync with configuration samples under `etc/`. + +> Remark (2025-10-13, DOC4.AUTH-PDG): Rate limit guide published (`docs/security/rate-limits.md`) and handed to plugin docs team for diagram uplift once PLG6.DIAGRAM lands. + +## Orchestrator Dashboard (Epic 9) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-ORCH-32-001 | TODO | Docs Guild | ORCH-SVC-32-001, AUTH-ORCH-32-001 | Author `/docs/orchestrator/overview.md` covering mission, roles, AOC alignment, governance, with imposed rule reminder. | Doc merged with diagrams; imposed rule statement included; entry linked from docs index. | +| DOCS-ORCH-32-002 | TODO | Docs Guild | ORCH-SVC-32-002 | Author `/docs/orchestrator/architecture.md` detailing scheduler, DAGs, rate limits, data model, message bus, storage layout, restating imposed rule. | Architecture doc merged; diagrams reviewed; imposed rule noted. | +| DOCS-ORCH-33-001 | TODO | Docs Guild | ORCH-SVC-33-001..004, WEB-ORCH-33-001 | Publish `/docs/orchestrator/api.md` (REST/WebSocket endpoints, payloads, error codes) with imposed rule note. | API doc merged; examples validated; imposed rule appended. | +| DOCS-ORCH-33-002 | TODO | Docs Guild | CONSOLE-ORCH-32-002, CONSOLE-ORCH-33-001..002 | Publish `/docs/orchestrator/console.md` covering screens, a11y, live updates, control actions, reiterating imposed rule. | Console doc merged with screenshots; accessibility checklist done; imposed rule statement present. | +| DOCS-ORCH-33-003 | TODO | Docs Guild | CLI-ORCH-33-001 | Publish `/docs/orchestrator/cli.md` documenting commands, options, exit codes, streaming output, offline usage, and imposed rule. | CLI doc merged; examples tested; imposed rule appended. | +| DOCS-ORCH-34-001 | TODO | Docs Guild | ORCH-SVC-34-002, LEDGER-34-101 | Author `/docs/orchestrator/run-ledger.md` covering ledger schema, provenance chain, audit workflows, with imposed rule reminder. | Run-ledger doc merged; payload samples validated; imposed rule included; cross-links added. | +| DOCS-ORCH-34-002 | TODO | Docs Guild | AUTH-ORCH-32-001, AUTH-ORCH-34-001 | Update `/docs/security/secrets-handling.md` for orchestrator KMS refs, redaction badges, operator hygiene, reiterating imposed rule. | Security doc merged; checklists updated; imposed rule restated; references from Console/CLI docs added. | +| DOCS-ORCH-34-003 | TODO | Docs Guild | ORCH-SVC-33-003, ORCH-SVC-34-001, DEVOPS-ORCH-34-001 | Publish `/docs/operations/orchestrator-runbook.md` (incident playbook, backfill guide, circuit breakers, throttling) with imposed rule statement. | Runbook merged; steps validated with DevOps; imposed rule included; runbook linked from ops index. | +| DOCS-ORCH-34-004 | TODO | Docs Guild | ORCH-SVC-32-005, WORKER-GO-33-001, WORKER-PY-33-001 | Document `/docs/schemas/artifacts.md` describing artifact kinds, schema versions, hashing, storage layout, restating imposed rule. | Schema doc merged; JSON schema provided; imposed rule included; sample payload validated. | +| DOCS-ORCH-34-005 | TODO | Docs Guild | ORCH-SVC-34-001, DEVOPS-ORCH-34-001 | Author `/docs/slo/orchestrator-slo.md` defining SLOs, burn alerts, measurement, and reiterating imposed rule. | SLO doc merged; dashboard screenshots embedded; imposed rule appended; alerts documented. | + +## Export Center (Epic 10) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-EXPORT-35-001 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-001..006 | Author `/docs/modules/export-center/overview.md` covering purpose, profiles, security, AOC alignment, surfaces, ending with imposed rule statement. | Doc merged with diagrams/examples; imposed rule line present; index updated. | +| DOCS-EXPORT-35-002 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-002..005 | Publish `/docs/modules/export-center/architecture.md` describing planner, adapters, manifests, signing, distribution flows, restating imposed rule. | Architecture doc merged; sequence diagrams included; rule statement appended. | +| DOCS-EXPORT-35-003 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-003..004 | Publish `/docs/modules/export-center/profiles.md` detailing schema fields, examples, compatibility, and imposed rule reminder. | Profiles doc merged; JSON schemas linked; imposed rule noted. | +| DOCS-EXPORT-36-004 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-36-001..004, WEB-EXPORT-36-001 | Publish `/docs/modules/export-center/api.md` covering endpoints, payloads, errors, and mention imposed rule. | API doc merged; examples validated; rule included. | +| DOCS-EXPORT-36-005 | DONE (2025-10-29) | Docs Guild | CLI-EXPORT-35-001, CLI-EXPORT-36-001 | Publish `/docs/modules/export-center/cli.md` with command reference, CI scripts, verification steps, restating imposed rule. | CLI doc merged; script snippets tested; rule appended. | +| DOCS-EXPORT-36-006 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-36-001, DEVOPS-EXPORT-36-001 | Publish `/docs/modules/export-center/trivy-adapter.md` covering field mappings, compatibility matrix, and imposed rule reminder. | Doc merged; mapping tables validated; rule included. | +| DOCS-EXPORT-37-001 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-37-001, DEVOPS-EXPORT-37-001 | Publish `/docs/modules/export-center/mirror-bundles.md` describing filesystem/OCI layouts, delta/encryption, import guide, ending with imposed rule. | Doc merged; diagrams provided; verification steps tested; rule stated. | +| DOCS-EXPORT-37-002 | DONE (2025-10-29) | Docs Guild | EXPORT-SVC-35-005, EXPORT-SVC-37-002 | Publish `/docs/modules/export-center/provenance-and-signing.md` detailing manifests, attestation flow, verification, reiterating imposed rule. | Doc merged; signature examples validated; rule appended. | +| DOCS-EXPORT-37-003 | DONE (2025-10-29) | Docs Guild | DEVOPS-EXPORT-37-001 | Publish `/docs/operations/export-runbook.md` covering failures, tuning, capacity planning, with imposed rule reminder. | Runbook merged; procedures validated; rule included. | +| DOCS-EXPORT-37-004 | TODO | Docs Guild | AUTH-EXPORT-37-001, EXPORT-SVC-37-002 | Publish `/docs/security/export-hardening.md` outlining RBAC, tenancy, encryption, redaction, restating imposed rule. | Security doc merged; checklist updated; rule appended. | +| DOCS-EXPORT-37-101 | TODO | Docs Guild, DevEx/CLI Guild | CLI-EXPORT-37-001 | Refresh CLI verification sections once `stella export verify` lands (flags, exit codes, samples). | `docs/modules/export-center/cli.md` & `docs/modules/export-center/provenance-and-signing.md` updated with final command syntax; examples tested; rule reminder retained. | +| DOCS-EXPORT-37-102 | TODO | Docs Guild, DevOps Guild | DEVOPS-EXPORT-37-001 | Embed export dashboards/alerts references into provenance/runbook docs after Grafana work ships. | Docs updated with dashboard IDs/alert notes; update logged; rule reminder present. | +| DOCS-EXPORT-37-005 | TODO | Docs Guild, Exporter Service Guild | EXPORT-SVC-35-006, DEVOPS-EXPORT-36-001 | Validate Export Center docs against live Trivy/mirror bundles once implementation lands; refresh examples and CLI snippets accordingly. | Real bundle examples recorded; docs updated; verification steps confirmed with production artefacts. | +> Note (2025-10-29): Blocked until exporter API (`EXPORT-SVC-35-006`) and Trivy/mirror adapters (`EXPORT-SVC-36-001`, `EXPORT-SVC-37-001`) ship. Requires access to CI smoke outputs (`DEVOPS-EXPORT-36-001`) for verification artifacts. + +## Reachability v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-SIG-26-001 | TODO | Docs Guild, Signals Guild | SIGNALS-24-004 | Write `/docs/signals/reachability.md` covering states, scores, provenance, retention. | Doc merged with diagrams/examples; checklist appended. | +| DOCS-SIG-26-002 | TODO | Docs Guild, Signals Guild | SIGNALS-24-002 | Publish `/docs/signals/callgraph-formats.md` with schemas and validation errors. | Doc merged; examples tested; checklist included. | +| DOCS-SIG-26-003 | TODO | Docs Guild, Runtime Guild | SIGNALS-24-003 | Create `/docs/signals/runtime-facts.md` detailing agent capabilities, privacy safeguards, opt-in flags. | Doc merged; privacy review done; checklist appended. | +| DOCS-SIG-26-004 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-80-001 | Document `/docs/policy/signals-weighting.md` for SPL predicates and weighting strategies. | Doc merged; sample policies validated; checklist appended. | +| DOCS-SIG-26-005 | TODO | Docs Guild, UI Guild | UI-SIG-26-001..003 | Draft `/docs/ui/reachability-overlays.md` with badges, timelines, shortcuts. | Doc merged with screenshots; accessibility checklist completed. | +| DOCS-SIG-26-006 | TODO | Docs Guild, DevEx/CLI Guild | CLI-SIG-26-001..002 | Update `/docs/modules/cli/guides/reachability.md` for new commands and automation recipes. | Doc merged; examples verified; checklist appended. | +| DOCS-SIG-26-007 | TODO | Docs Guild, BE-Base Platform Guild | WEB-SIG-26-001..003 | Publish `/docs/api/signals.md` covering endpoints, payloads, ETags, errors. | API doc aligned with OpenAPI; examples tested; checklist appended. | +| DOCS-SIG-26-008 | TODO | Docs Guild, DevOps Guild | DEVOPS-SIG-26-001..002 | Write `/docs/migration/enable-reachability.md` guiding rollout, fallbacks, monitoring. | Migration doc approved; checklist appended. | + +## Policy Studio (Sprint 27) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-POLICY-27-001 | BLOCKED (2025-10-27) | Docs Guild, Policy Guild | REGISTRY-API-27-001, POLICY-ENGINE-27-001 | Publish `/docs/policy/studio-overview.md` covering lifecycle, roles, glossary, and compliance checklist. | Doc merged with diagrams + lifecycle table; checklist appended; stakeholders sign off. | +> Blocked by `REGISTRY-API-27-001` and `POLICY-ENGINE-27-001`; need spec + compile data. +> Blocker: Registry OpenAPI (`REGISTRY-API-27-001`) and policy compile enrichments (`POLICY-ENGINE-27-001`) are still TODO; need final interfaces before drafting overview. +| DOCS-POLICY-27-002 | BLOCKED (2025-10-27) | Docs Guild, Console Guild | CONSOLE-STUDIO-27-001 | Write `/docs/policy/authoring.md` detailing workspace templates, snippets, lint rules, IDE shortcuts, and best practices. | Authoring doc includes annotated screenshots, snippet catalog, compliance checklist. | +> Blocked by `CONSOLE-STUDIO-27-001` Studio authoring UI pending. +> Blocker: Console Studio authoring UI (`CONSOLE-STUDIO-27-001`) not implemented; awaiting UX to capture flows/snippets. +| DOCS-POLICY-27-003 | BLOCKED (2025-10-27) | Docs Guild, Policy Registry Guild | REGISTRY-API-27-007 | Document `/docs/policy/versioning-and-publishing.md` (semver rules, attestations, rollback) with compliance checklist. | Doc merged with flow diagrams; attestation steps documented; checklist appended. | +> Blocked by `REGISTRY-API-27-007` publish/sign pipeline outstanding. +> Blocker: Registry publish/sign workflow (`REGISTRY-API-27-007`) pending. +| DOCS-POLICY-27-004 | BLOCKED (2025-10-27) | Docs Guild, Scheduler Guild | REGISTRY-API-27-005, SCHED-WORKER-27-301 | Write `/docs/policy/simulation.md` covering quick vs batch sim, thresholds, evidence bundles, CLI examples. | Simulation doc includes charts, sample manifests, checklist appended. | +> Blocked by `REGISTRY-API-27-005`/`SCHED-WORKER-27-301` batch simulation not ready. +> Blocker: Batch simulation APIs/workers (`REGISTRY-API-27-005`, `SCHED-WORKER-27-301`) still TODO. +| DOCS-POLICY-27-005 | BLOCKED (2025-10-27) | Docs Guild, Product Ops | REGISTRY-API-27-006 | Publish `/docs/policy/review-and-approval.md` with approver requirements, comments, webhooks, audit trail guidance. | Doc merged with role matrix + webhook schema; checklist appended. | +> Blocked by `REGISTRY-API-27-006` review workflow not implemented. +> Blocker: Review workflow (`REGISTRY-API-27-006`) not landed. +| DOCS-POLICY-27-006 | BLOCKED (2025-10-27) | Docs Guild, Policy Guild | REGISTRY-API-27-008 | Author `/docs/policy/promotion.md` covering environments, canary, rollback, and monitoring steps. | Promotion doc includes examples + checklist; verified by Policy Ops. | +> Blocked by `REGISTRY-API-27-008` promotion APIs pending. +> Blocker: Promotion/canary APIs (`REGISTRY-API-27-008`) outstanding. +| DOCS-POLICY-27-007 | BLOCKED (2025-10-27) | Docs Guild, DevEx/CLI Guild | CLI-POLICY-27-001..004 | Update `/docs/policy/cli.md` with new commands, JSON schemas, CI usage, and compliance checklist. | CLI doc merged with transcripts; schema references validated; checklist appended. | +> Blocked by `CLI-POLICY-27-001..004` CLI commands missing. +> Blocker: Policy CLI commands (`CLI-POLICY-27-001..004`) yet to implement. +| DOCS-POLICY-27-008 | BLOCKED (2025-10-27) | Docs Guild, Policy Registry Guild | REGISTRY-API-27-001..008 | Publish `/docs/policy/api.md` describing Registry endpoints, request/response schemas, errors, and feature flags. | API doc aligned with OpenAPI; examples validated; checklist appended. | +> Blocked by `REGISTRY-API-27-001..008` OpenAPI + endpoints incomplete. +> Blocker: Registry OpenAPI/spec suite (`REGISTRY-API-27-001..008`) incomplete. +| DOCS-POLICY-27-009 | BLOCKED (2025-10-27) | Docs Guild, Security Guild | AUTH-POLICY-27-002 | Create `/docs/security/policy-attestations.md` covering signing, verification, key rotation, and compliance checklist. | Security doc approved by Security Guild; verifier steps documented; checklist appended. | +> Blocked by `AUTH-POLICY-27-002` signing enforcement pending. +> Blocker: Authority signing enforcement (`AUTH-POLICY-27-002`) pending. +| DOCS-POLICY-27-010 | BLOCKED (2025-10-27) | Docs Guild, Architecture Guild | REGISTRY-API-27-001, SCHED-WORKER-27-301 | Author `/docs/modules/policy/registry-architecture.md` (service design, schemas, queues, failure modes) with diagrams and checklist. | Architecture doc merged; diagrams committed; checklist appended. | +> Blocked by `REGISTRY-API-27-001` & `SCHED-WORKER-27-301` need delivery. +> Blocker: Policy Registry schema/workers not delivered (see `REGISTRY-API-27-001`, `SCHED-WORKER-27-301`). +| DOCS-POLICY-27-011 | BLOCKED (2025-10-27) | Docs Guild, Observability Guild | DEVOPS-POLICY-27-004 | Publish `/docs/observability/policy-telemetry.md` with metrics/log tables, dashboards, alerts, and compliance checklist. | Observability doc merged; dashboards linked; checklist appended. | +> Blocked by `DEVOPS-POLICY-27-004` observability dashboards outstanding. +> Blocker: Observability dashboards (`DEVOPS-POLICY-27-004`) not built. +| DOCS-POLICY-27-012 | BLOCKED (2025-10-27) | Docs Guild, Ops Guild | DEPLOY-POLICY-27-002 | Write `/docs/runbooks/policy-incident.md` detailing rollback, freeze, forensic steps, notifications. | Runbook merged; rehearsal recorded; checklist appended. | +> Blocked by `DEPLOY-POLICY-27-002` incident runbook inputs pending. +> Blocker: Ops runbook inputs (`DEPLOY-POLICY-27-002`) pending. +| DOCS-POLICY-27-013 | BLOCKED (2025-10-27) | Docs Guild, Policy Guild | CONSOLE-STUDIO-27-001, REGISTRY-API-27-002 | Update `/docs/examples/policy-templates.md` with new templates, snippets, and sample policies. | Examples committed with commentary; lint passes; checklist appended. | +> Blocked by `CONSOLE-STUDIO-27-001`/`REGISTRY-API-27-002` templates missing. +> Blocker: Studio templates and registry storage (`CONSOLE-STUDIO-27-001`, `REGISTRY-API-27-002`) not available. +| DOCS-POLICY-27-014 | BLOCKED (2025-10-27) | Docs Guild, Policy Registry Guild | REGISTRY-API-27-003, WEB-POLICY-27-001 | Refresh `/docs/aoc/aoc-guardrails.md` to include Studio-specific guardrails and validation scenarios. | Doc updated with Studio guardrails; compliance checklist appended. | +> Blocked by `REGISTRY-API-27-003` & `WEB-POLICY-27-001` guardrails not implemented. +> Blocker: Registry compile pipeline/web proxy (`REGISTRY-API-27-003`, `WEB-POLICY-27-001`) outstanding. + +## Vulnerability Explorer (Sprint 29) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-VULN-29-001 | TODO | Docs Guild, Vuln Explorer Guild | VULN-API-29-001 | Publish `/docs/vuln/explorer-overview.md` covering domain model, identities, AOC guarantees, workflow summary. | Doc merged with diagrams/table; compliance checklist appended. | +| DOCS-VULN-29-002 | TODO | Docs Guild, Console Guild | CONSOLE-VULN-29-001..006 | Write `/docs/vuln/explorer-using-console.md` with workflows, screenshots, keyboard shortcuts, saved views, deep links. | Doc merged; images stored; WCAG notes included; checklist appended. | +| DOCS-VULN-29-003 | TODO | Docs Guild, Vuln Explorer API Guild | VULN-API-29-001..009 | Author `/docs/vuln/explorer-api.md` (endpoints, query schema, grouping, errors, rate limits). | Doc aligned with OpenAPI; examples validated; checklist appended. | +| DOCS-VULN-29-004 | TODO | Docs Guild, DevEx/CLI Guild | CLI-VULN-29-001..005 | Publish `/docs/vuln/explorer-cli.md` with command reference, samples, exit codes, CI snippets. | CLI doc merged; transcripts/JSON outputs validated; checklist appended. | +| DOCS-VULN-29-005 | TODO | Docs Guild, Findings Ledger Guild | LEDGER-29-001..009 | Write `/docs/vuln/findings-ledger.md` detailing event schema, hashing, Merkle roots, replay tooling. | Doc merged; compliance checklist appended; audit team sign-off. | +| DOCS-VULN-29-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-29-001..003 | Update `/docs/policy/vuln-determinations.md` for new rationale, signals, simulation semantics. | Doc updated; examples validated; checklist appended. | +| DOCS-VULN-29-007 | TODO | Docs Guild, Excititor Guild | EXCITITOR-VULN-29-001..004 | Publish `/docs/vex/explorer-integration.md` covering CSAF mapping, suppression precedence, status semantics. | Doc merged; compliance checklist appended. | +| DOCS-VULN-29-008 | TODO | Docs Guild, Concelier Guild | CONCELIER-VULN-29-001..004 | Publish `/docs/advisories/explorer-integration.md` covering key normalization, withdrawn handling, provenance. | Doc merged; checklist appended. | +| DOCS-VULN-29-009 | TODO | Docs Guild, SBOM Service Guild | SBOM-VULN-29-001..002 | Author `/docs/sbom/vuln-resolution.md` detailing version semantics, scope, paths, safe version hints. | Doc merged; ecosystem tables validated; checklist appended. | +| DOCS-VULN-29-010 | TODO | Docs Guild, Observability Guild | VULN-API-29-009, DEVOPS-VULN-29-002 | Publish `/docs/observability/vuln-telemetry.md` (metrics, logs, tracing, dashboards, SLOs). | Doc merged; dashboards linked; checklist appended. | +| DOCS-VULN-29-011 | TODO | Docs Guild, Security Guild | AUTH-VULN-29-001..003 | Create `/docs/security/vuln-rbac.md` for roles, ABAC policies, attachment encryption, CSRF. | Security doc approved; checklist appended. | +| DOCS-VULN-29-012 | TODO | Docs Guild, Ops Guild | DEVOPS-VULN-29-002, SCHED-WORKER-29-003 | Write `/docs/runbooks/vuln-ops.md` (projector lag, resolver storms, export failures, policy activation). | Runbook merged; rehearsal recorded; checklist appended. | +| DOCS-VULN-29-013 | TODO | Docs Guild, Deployment Guild | DEPLOY-VULN-29-001..002 | Update `/docs/install/containers.md` with Findings Ledger & Vuln Explorer API images, manifests, resource sizing, health checks. | Install doc updated; validation commands included; checklist appended. | + +## VEX Lens (Sprint 30) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-VEX-30-001 | TODO | Docs Guild, VEX Lens Guild | VEXLENS-30-005 | Publish `/docs/vex/consensus-overview.md` describing purpose, scope, AOC guarantees. | Doc merged with diagrams/terminology tables; compliance checklist appended. | +| DOCS-VEX-30-002 | TODO | Docs Guild, VEX Lens Guild | VEXLENS-30-005 | Author `/docs/vex/consensus-algorithm.md` covering normalization, weighting, thresholds, examples. | Doc merged; math reviewed by Policy; checklist appended. | +| DOCS-VEX-30-003 | TODO | Docs Guild, Issuer Directory Guild | ISSUER-30-001..003 | Document `/docs/vex/issuer-directory.md` (issuer management, keys, trust overrides, audit). | Doc merged; security review done; checklist appended. | +| DOCS-VEX-30-004 | TODO | Docs Guild, VEX Lens Guild | VEXLENS-30-007 | Publish `/docs/vex/consensus-api.md` with endpoint specs, query params, rate limits. | API doc aligned with OpenAPI; examples validated; checklist appended. | +| DOCS-VEX-30-005 | TODO | Docs Guild, Console Guild | CONSOLE-VEX-30-001 | Write `/docs/vex/consensus-console.md` covering UI workflows, filters, conflicts, accessibility. | Doc merged; screenshots added; checklist appended. | +| DOCS-VEX-30-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-29-001, VEXLENS-30-004 | Add `/docs/policy/vex-trust-model.md` detailing policy knobs, thresholds, simulation. | Doc merged; policy review completed; checklist appended. | +| DOCS-VEX-30-007 | TODO | Docs Guild, SBOM Service Guild | VEXLENS-30-002 | Publish `/docs/sbom/vex-mapping.md` (CPE→purl strategy, edge cases, overrides). | Doc merged; mapping tables validated; checklist appended. | +| DOCS-VEX-30-008 | TODO | Docs Guild, Security Guild | ISSUER-30-002, VEXLENS-30-003 | Deliver `/docs/security/vex-signatures.md` (verification flow, key rotation, audit). | Doc approved by Security; checklist appended. | +| DOCS-VEX-30-009 | TODO | Docs Guild, DevOps Guild | VEXLENS-30-009, DEVOPS-VEX-30-001 | Create `/docs/runbooks/vex-ops.md` for recompute storms, mapping failures, signature errors. | Runbook merged; rehearsal logged; checklist appended. | + +## Advisory AI (Sprint 31) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-AIAI-31-001 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-006 | Publish `/docs/advisory-ai/overview.md` covering capabilities, guardrails, RBAC. | Doc merged with diagrams; compliance checklist appended. | +| DOCS-AIAI-31-002 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-004 | Author `/docs/advisory-ai/architecture.md` detailing RAG pipeline, deterministics, caching, model options. | Doc merged; architecture review done; checklist appended. | +| DOCS-AIAI-31-003 | TODO | Docs Guild, Advisory AI Guild | AIAI-31-006 | Write `/docs/advisory-ai/api.md` describing endpoints, schemas, errors, rate limits. | API doc aligned with OpenAPI; examples validated; checklist appended. | +| DOCS-AIAI-31-004 | TODO | Docs Guild, Console Guild | CONSOLE-VULN-29-001, CONSOLE-VEX-30-001 | Create `/docs/advisory-ai/console.md` with screenshots, a11y notes, copy-as-ticket instructions. | Doc merged; images stored; checklist appended. | +| DOCS-AIAI-31-005 | TODO | Docs Guild, DevEx/CLI Guild | CLI-VULN-29-001, CLI-VEX-30-001 | Publish `/docs/advisory-ai/cli.md` covering commands, exit codes, scripting patterns. | Doc merged; examples tested; checklist appended. | +| DOCS-AIAI-31-006 | TODO | Docs Guild, Policy Guild | POLICY-ENGINE-31-001 | Update `/docs/policy/assistant-parameters.md` covering temperature, token limits, ranking weights, TTLs. | Doc merged; policy review done; checklist appended. | +| DOCS-AIAI-31-007 | TODO | Docs Guild, Security Guild | AIAI-31-005 | Write `/docs/security/assistant-guardrails.md` detailing redaction, injection defense, logging. | Doc approved by Security; checklist appended. | +| DOCS-AIAI-31-008 | TODO | Docs Guild, SBOM Service Guild | SBOM-AIAI-31-001 | Publish `/docs/sbom/remediation-heuristics.md` (feasibility scoring, blast radius). | Doc merged; heuristics reviewed; checklist appended. | +| DOCS-AIAI-31-009 | TODO | Docs Guild, DevOps Guild | DEVOPS-AIAI-31-001 | Create `/docs/runbooks/assistant-ops.md` for warmup, cache priming, model outages, scaling. | Runbook merged; rehearsal logged; checklist appended. | + +## Notifications Studio + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-NOTIFY-38-001 | DONE (2025-10-29) | Docs Guild, Notifications Service Guild | NOTIFY-SVC-38-001..004 | Publish `/docs/notifications/overview.md` and `/docs/notifications/architecture.md`, each ending with imposed rule reminder. | Docs merged; diagrams verified; imposed rule appended. | +| DOCS-NOTIFY-39-002 | DONE (2025-10-29) | Docs Guild, Notifications Service Guild | NOTIFY-SVC-39-001..004 | Publish `/docs/notifications/rules.md`, `/docs/notifications/templates.md`, `/docs/notifications/digests.md` with examples and imposed rule line. | Docs merged; examples validated; imposed rule appended. | +| DOCS-NOTIFY-40-001 | TODO | Docs Guild, Security Guild | AUTH-NOTIFY-38-001, NOTIFY-SVC-40-001..004 | Publish `/docs/notifications/channels.md`, `/docs/notifications/escalations.md`, `/docs/notifications/api.md`, `/docs/operations/notifier-runbook.md`, `/docs/security/notifications-hardening.md`; each ends with imposed rule line. | Docs merged; accessibility checks passed; imposed rule appended. | + +## CLI Parity & Task Packs + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-CLI-41-001 | TODO | Docs Guild, DevEx/CLI Guild | CLI-CORE-41-001 | Publish `/docs/modules/cli/guides/overview.md`, `/docs/modules/cli/guides/configuration.md`, `/docs/modules/cli/guides/output-and-exit-codes.md` with imposed rule statements. | Docs merged; examples verified; imposed rule appended. | +| DOCS-CLI-42-001 | TODO | Docs Guild | DOCS-CLI-41-001, CLI-PARITY-41-001 | Publish `/docs/modules/cli/guides/parity-matrix.md` and command guides under `/docs/modules/cli/guides/commands/*.md` (policy, sbom, vuln, vex, advisory, export, orchestrator, notify, aoc, auth). | Guides merged; parity automation documented; imposed rule appended. | +| DOCS-PACKS-43-001 | DONE (2025-10-27) | Docs Guild, Task Runner Guild | PACKS-REG-42-001, TASKRUN-42-001 | Publish `/docs/task-packs/spec.md`, `/docs/task-packs/authoring-guide.md`, `/docs/task-packs/registry.md`, `/docs/task-packs/runbook.md`, `/docs/security/pack-signing-and-rbac.md`, `/docs/operations/cli-release-and-packaging.md` with imposed rule statements. | Docs merged; tutorials validated; imposed rule appended; cross-links added. | + +## Containerized Distribution (Epic 13) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-INSTALL-44-001 | TODO | Docs Guild, Deployment Guild | COMPOSE-44-001 | Publish `/docs/install/overview.md` and `/docs/install/compose-quickstart.md` with imposed rule line and copy-ready commands. | Docs merged; screenshots/commands verified; imposed rule appended. | +| DOCS-INSTALL-45-001 | TODO | Docs Guild, Deployment Guild | HELM-45-001 | Publish `/docs/install/helm-prod.md` and `/docs/install/configuration-reference.md` with values tables and imposed rule reminder. | Docs merged; configuration matrix verified; imposed rule appended. | +| DOCS-INSTALL-46-001 | TODO | Docs Guild, Security Guild | DEPLOY-PACKS-43-001, CLI-PACKS-43-001 | Publish `/docs/install/airgap.md`, `/docs/security/supply-chain.md`, `/docs/operations/health-and-readiness.md`, `/docs/release/image-catalog.md`, `/docs/console/onboarding.md` (each with imposed rule). | Docs merged; checksum/signature sections validated; imposed rule appended. | + +## Authority-Backed Scopes & Tenancy (Epic 14) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCS-TEN-47-001 | TODO | Docs Guild, Authority Core | AUTH-TEN-47-001 | Publish `/docs/security/tenancy-overview.md` and `/docs/security/scopes-and-roles.md` outlining scope grammar, tenant model, imposed rule reminder. | Docs merged; diagrams included; imposed rule appended. | +| DOCS-TEN-48-001 | TODO | Docs Guild, Platform Ops | WEB-TEN-48-001 | Publish `/docs/operations/multi-tenancy.md`, `/docs/operations/rls-and-data-isolation.md`, `/docs/console/admin-tenants.md`. | Docs merged; examples validated; imposed rule appended. | +| DOCS-TEN-49-001 | TODO | Docs & DevEx Guilds | CLI-TEN-47-001, AUTH-TEN-49-001 | Publish `/docs/modules/cli/guides/authentication.md`, `/docs/api/authentication.md`, `/docs/policy/examples/abac-overlays.md`, update `/docs/install/configuration-reference.md` with new env vars, all ending with imposed rule line. | Docs merged; command examples verified; imposed rule appended. | diff --git a/docs/accessibility.md b/docs/accessibility.md index 09be0df3..08013614 100644 --- a/docs/accessibility.md +++ b/docs/accessibility.md @@ -1,131 +1,131 @@ -# StellaOps Console Accessibility Guide - -> **Audience:** Accessibility Guild, Console Guild, Docs Guild, QA. -> **Scope:** Keyboard interaction model, screen-reader behaviour, colour & focus tokens, testing workflows, offline considerations, and compliance checklist for the StellaOps Console (Sprint 23). - -The console targets **WCAG 2.2 AA** across all supported browsers (Chromium, Firefox ESR) and honours StellaOps’ sovereign/offline constraints. Every build must keep keyboard-only users, screen-reader users, and high-contrast operators productive without relying on third-party services. - ---- - -## 1 · Accessibility Principles - -1. **Deterministic navigation** – Focus order, shortcuts, and announcements remain stable across releases; URLs encode state for deep links. -2. **Keyboard-first design** – Every actionable element is reachable via keyboard; shortcuts provide accelerators, and remapping is available via *Settings → Accessibility → Keyboard shortcuts*. -3. **Assistive technology parity** – ARIA roles and live regions mirror visual affordances (status banners, SSE tickers, progress drawers). Screen readers receive polite/atomic updates to avoid chatter. -4. **Colour & contrast tokens** – All palettes derive from design tokens that achieve ≥ 4.5:1 contrast (text) and ≥ 3:1 for graphical indicators; tokens pass automated contrast linting. -5. **Offline equivalence** – Accessibility features (shortcuts, offline banners, focus restoration) behave the same in sealed environments, with guidance when actions require online authority. - ---- - -## 2 · Keyboard Interaction Map - -### 2.1 Global shortcuts - -| Action | Macs | Windows/Linux | Notes | -|--------|------|---------------|-------| -| Command palette | `⌘ K` | `Ctrl K` | Focuses palette search; respects tenant scope. | -| Tenant picker | `⌘ T` | `Ctrl T` | Opens modal; `Enter` confirms, `Esc` cancels. | -| Filter tray toggle | `⇧ F` | `Shift F` | Focus lands on first filter; `Tab` cycles filters before returning to page. | -| Saved view presets | `⌘ 1-9` | `Ctrl 1-9` | Bound per tenant; missing preset triggers tooltip. | -| Keyboard reference | `?` | `?` | Opens overlay listing context-specific shortcuts; `Esc` closes. | -| Global search (context) | `/` | `/` | When the filter tray is closed, focuses inline search field. | - -### 2.2 Module-specific shortcuts - -| Module | Action | Macs | Windows/Linux | Notes | -|--------|--------|------|---------------|-------| -| Findings | Explain search | `⌘ /` | `Ctrl /` | Only when Explain drawer open; announces results via live region. | -| SBOM Explorer | Toggle overlays | `⌘ G` | `Ctrl G` | Persists per session (see `/docs/ui/sbom-explorer.md`). | -| Advisories & VEX | Provider filter | `⌘ ⌥ F` | `Ctrl Alt F` | Moves focus to provider chip row. | -| Runs | Refresh snapshot | `⌘ R` | `Ctrl R` | Soft refresh of SSE state; no full page reload. | -| Policies | Save draft | `⌘ S` | `Ctrl S` | Requires edit scope; exposes toast + status live update. | -| Downloads | Copy CLI command | `⇧ D` | `Shift D` | Copies manifest or export command; toast announces scope hints. | - -All shortcuts are remappable. Remaps persist in IndexedDB (per tenant) and export as part of profile bundles so operators can restore preferences offline. - ---- - -## 3 · Screen Reader & Focus Behaviour - -- **Skip navigation** – Each route exposes a “Skip to content” link revealed on keyboard focus. Focus order: global header → page breadcrumb → action shelf → data grid/list → drawers/dialogs. -- **Live regions** – Status ticker and SSE progress bars use `aria-live="polite"` with throttling to avoid flooding AT. Error toasts use `aria-live="assertive"` and auto-focus dismiss buttons. -- **Drawers & modals** – Dialog components trap focus, support `Esc` to close, and restore focus to the launching control. Screen readers announce title + purpose. -- **Tables & grids** – Large tables (Findings, SBOM inventory) switch to virtualised rows but retain ARIA grid semantics (`aria-rowcount`, `aria-colindex`). Column headers include sorting state via `aria-sort`. -- **Tenancy context** – Tenant badge exposes `aria-describedby` linking to context summary (environment, offline snapshot). Switching tenant queues a polite announcement summarising new scope. -- **Command palette** – Uses `role="dialog"` with search input labelled. Keyboard navigation within results uses `Up/Down`; screen readers announce result category + command. -- **Offline banner** – When offline, a dismissible banner announces reason and includes instructions for CLI fallback. The banner has `role="status"` so it announces once without stealing focus. - ---- - -## 4 · Colour & Focus Tokens - -Console consumes design tokens published by the Console Guild (tracked via CONSOLE-FEAT-23-102). Tokens live in the design system bundle (`ui/design/tokens/colors.json`, mirrored at build time). Key tokens: - -| Token | Purpose | Contrast target | -|-------|---------|-----------------| -| `so-color-surface-base` | Primary surface/background | ≥ 4.5:1 against `so-color-text-primary`. | -| `so-color-surface-raised` | Cards, drawers, modals | ≥ 3:1 against surrounding surfaces. | -| `so-color-text-primary` | Default text colour | ≥ 4.5:1 against base surfaces. | -| `so-color-text-inverted` | Text on accent buttons | ≥ 4.5:1 against accent fills. | -| `so-color-accent-primary` | Action buttons, focus headings | ≥ 3:1 against surface. | -| `so-color-status-critical` | Error toasts, violation chips | ≥ 4.5:1 for text; `critical-bg` provides >3:1 on neutral surface. | -| `so-color-status-warning` | Warning banners | Meets 3:1 on surface and 4.5:1 for text overlays. | -| `so-color-status-success` | Success toasts, pass badges | ≥ 3:1 for iconography; text uses `text-primary`. | -| `so-focus-ring` | 2 px outline used across focusable elements | 3:1 against both light/dark surfaces. | - -Colour tokens undergo automated linting (**axe-core contrast checks** + custom luminance script) during build. Any new token must include dark/light variants and pass the token contract tests. - ---- - -## 5 · Testing Workflow - -| Layer | Tooling | Frequency | Notes | -|-------|---------|-----------|-------| -| Component a11y | Storybook + axe-core addon | On PR (story CI) | Fails when axe detects violations. | -| Route regression | Playwright a11y sweep (`pnpm test:a11y`) | Nightly & release pipeline | Executes keyboard navigation, checks focus trap, runs Axe on key routes (Dashboard, Findings, SBOM, Admin). | -| Colour contrast lint | Token validator (`tools/a11y/check-contrast.ts`) | On token change | Guards design token updates. | -| CI parity | Pending `scripts/check-console-cli-parity.sh` (CONSOLE-DOC-23-502) | Release CI | Ensures CLI commands documented for parity features. | -| Screen-reader spot checks | Manual NVDA + VoiceOver scripts | Pre-release checklist | Scenarios: tenant switch, explain drawer, downloads parity copy. | -| Offline smoke | `stella offline kit import` + Playwright sealed-mode run | Prior to Offline Kit cut | Validates offline banners, disabled actions, keyboard flows without Authority. | - -Accessibility QA (CONSOLE-QA-23-402) tracks failing scenarios via Playwright snapshots and publishes reports in the Downloads parity channel (`kind = "parity.report"` placeholder until CLI parity CI lands). - ---- - -## 6 · Offline & Internationalisation Considerations - -- Offline mode surfaces staleness badges and disables remote-only palette entries; keyboard focus skips disabled controls. -- Saved shortcuts, presets, and remaps serialise into Offline Kit bundles so operators can restore preferences post-import. -- Locale switching (future feature flag) will load translations at runtime; ensure ARIA labels use i18n tokens rather than hard-coded strings. -- For sealed installs, guidance panels include CLI equivalents (`stella auth fresh-auth`, `stella runs export`) to unblock tasks when Authority is unavailable. - ---- - -## 7 · Compliance Checklist - -- [ ] Keyboard shortcut matrix validated (default + remapped) and documented. -- [ ] Screen-reader pass recorded for tenant switch, Explain drawer, Downloads copy-to-clipboard. -- [ ] Colour tokens audited; contrast reports stored with release artifacts. -- [ ] Automated a11y pipelines (Storybook axe, Playwright a11y) green; failures feed the `#console-qa` channel. -- [ ] Offline kit a11y smoke executed before publishing each bundle. -- [ ] CLI parity gaps logged in `/docs/cli-vs-ui-parity.md`; UI callouts reference fallback commands until parity closes. -- [ ] Accessibility Guild sign-off captured in sprint log and release notes reference this guide. -- [ ] References cross-checked (`/docs/ui/navigation.md`, `/docs/ui/downloads.md`, `/docs/security/console-security.md`, `/docs/observability/ui-telemetry.md`). - ---- - -## 8 · References - -- `/docs/ui/navigation.md` – shortcut definitions, URL schema. -- `/docs/ui/downloads.md` – CLI parity and offline copy workflows. -- `/docs/ui/console-overview.md` – tenant model, filter behaviours. -- `/docs/security/console-security.md` – security metrics and DPoP/fresh-auth requirements. -- `/docs/observability/ui-telemetry.md` – telemetry metrics mapped to accessibility features. -- `/docs/cli-vs-ui-parity.md` – parity status per console feature. -- `CONSOLE-QA-23-402` – Accessibility QA backlog (Playwright + manual checks). -- `CONSOLE-FEAT-23-102` – Design tokens & theming delivery. - ---- - -*Last updated: 2025-10-28 (Sprint 23).* - +# StellaOps Console Accessibility Guide + +> **Audience:** Accessibility Guild, Console Guild, Docs Guild, QA. +> **Scope:** Keyboard interaction model, screen-reader behaviour, colour & focus tokens, testing workflows, offline considerations, and compliance checklist for the StellaOps Console (Sprint 23). + +The console targets **WCAG 2.2 AA** across all supported browsers (Chromium, Firefox ESR) and honours StellaOps’ sovereign/offline constraints. Every build must keep keyboard-only users, screen-reader users, and high-contrast operators productive without relying on third-party services. + +--- + +## 1 · Accessibility Principles + +1. **Deterministic navigation** – Focus order, shortcuts, and announcements remain stable across releases; URLs encode state for deep links. +2. **Keyboard-first design** – Every actionable element is reachable via keyboard; shortcuts provide accelerators, and remapping is available via *Settings → Accessibility → Keyboard shortcuts*. +3. **Assistive technology parity** – ARIA roles and live regions mirror visual affordances (status banners, SSE tickers, progress drawers). Screen readers receive polite/atomic updates to avoid chatter. +4. **Colour & contrast tokens** – All palettes derive from design tokens that achieve ≥ 4.5:1 contrast (text) and ≥ 3:1 for graphical indicators; tokens pass automated contrast linting. +5. **Offline equivalence** – Accessibility features (shortcuts, offline banners, focus restoration) behave the same in sealed environments, with guidance when actions require online authority. + +--- + +## 2 · Keyboard Interaction Map + +### 2.1 Global shortcuts + +| Action | Macs | Windows/Linux | Notes | +|--------|------|---------------|-------| +| Command palette | `⌘ K` | `Ctrl K` | Focuses palette search; respects tenant scope. | +| Tenant picker | `⌘ T` | `Ctrl T` | Opens modal; `Enter` confirms, `Esc` cancels. | +| Filter tray toggle | `⇧ F` | `Shift F` | Focus lands on first filter; `Tab` cycles filters before returning to page. | +| Saved view presets | `⌘ 1-9` | `Ctrl 1-9` | Bound per tenant; missing preset triggers tooltip. | +| Keyboard reference | `?` | `?` | Opens overlay listing context-specific shortcuts; `Esc` closes. | +| Global search (context) | `/` | `/` | When the filter tray is closed, focuses inline search field. | + +### 2.2 Module-specific shortcuts + +| Module | Action | Macs | Windows/Linux | Notes | +|--------|--------|------|---------------|-------| +| Findings | Explain search | `⌘ /` | `Ctrl /` | Only when Explain drawer open; announces results via live region. | +| SBOM Explorer | Toggle overlays | `⌘ G` | `Ctrl G` | Persists per session (see `/docs/ui/sbom-explorer.md`). | +| Advisories & VEX | Provider filter | `⌘ ⌥ F` | `Ctrl Alt F` | Moves focus to provider chip row. | +| Runs | Refresh snapshot | `⌘ R` | `Ctrl R` | Soft refresh of SSE state; no full page reload. | +| Policies | Save draft | `⌘ S` | `Ctrl S` | Requires edit scope; exposes toast + status live update. | +| Downloads | Copy CLI command | `⇧ D` | `Shift D` | Copies manifest or export command; toast announces scope hints. | + +All shortcuts are remappable. Remaps persist in IndexedDB (per tenant) and export as part of profile bundles so operators can restore preferences offline. + +--- + +## 3 · Screen Reader & Focus Behaviour + +- **Skip navigation** – Each route exposes a “Skip to content” link revealed on keyboard focus. Focus order: global header → page breadcrumb → action shelf → data grid/list → drawers/dialogs. +- **Live regions** – Status ticker and SSE progress bars use `aria-live="polite"` with throttling to avoid flooding AT. Error toasts use `aria-live="assertive"` and auto-focus dismiss buttons. +- **Drawers & modals** – Dialog components trap focus, support `Esc` to close, and restore focus to the launching control. Screen readers announce title + purpose. +- **Tables & grids** – Large tables (Findings, SBOM inventory) switch to virtualised rows but retain ARIA grid semantics (`aria-rowcount`, `aria-colindex`). Column headers include sorting state via `aria-sort`. +- **Tenancy context** – Tenant badge exposes `aria-describedby` linking to context summary (environment, offline snapshot). Switching tenant queues a polite announcement summarising new scope. +- **Command palette** – Uses `role="dialog"` with search input labelled. Keyboard navigation within results uses `Up/Down`; screen readers announce result category + command. +- **Offline banner** – When offline, a dismissible banner announces reason and includes instructions for CLI fallback. The banner has `role="status"` so it announces once without stealing focus. + +--- + +## 4 · Colour & Focus Tokens + +Console consumes design tokens published by the Console Guild (tracked via CONSOLE-FEAT-23-102). Tokens live in the design system bundle (`ui/design/tokens/colors.json`, mirrored at build time). Key tokens: + +| Token | Purpose | Contrast target | +|-------|---------|-----------------| +| `so-color-surface-base` | Primary surface/background | ≥ 4.5:1 against `so-color-text-primary`. | +| `so-color-surface-raised` | Cards, drawers, modals | ≥ 3:1 against surrounding surfaces. | +| `so-color-text-primary` | Default text colour | ≥ 4.5:1 against base surfaces. | +| `so-color-text-inverted` | Text on accent buttons | ≥ 4.5:1 against accent fills. | +| `so-color-accent-primary` | Action buttons, focus headings | ≥ 3:1 against surface. | +| `so-color-status-critical` | Error toasts, violation chips | ≥ 4.5:1 for text; `critical-bg` provides >3:1 on neutral surface. | +| `so-color-status-warning` | Warning banners | Meets 3:1 on surface and 4.5:1 for text overlays. | +| `so-color-status-success` | Success toasts, pass badges | ≥ 3:1 for iconography; text uses `text-primary`. | +| `so-focus-ring` | 2 px outline used across focusable elements | 3:1 against both light/dark surfaces. | + +Colour tokens undergo automated linting (**axe-core contrast checks** + custom luminance script) during build. Any new token must include dark/light variants and pass the token contract tests. + +--- + +## 5 · Testing Workflow + +| Layer | Tooling | Frequency | Notes | +|-------|---------|-----------|-------| +| Component a11y | Storybook + axe-core addon | On PR (story CI) | Fails when axe detects violations. | +| Route regression | Playwright a11y sweep (`pnpm test:a11y`) | Nightly & release pipeline | Executes keyboard navigation, checks focus trap, runs Axe on key routes (Dashboard, Findings, SBOM, Admin). | +| Colour contrast lint | Token validator (`src/Tools/a11y/check-contrast.ts`) | On token change | Guards design token updates. | +| CI parity | Pending `scripts/check-console-cli-parity.sh` (CONSOLE-DOC-23-502) | Release CI | Ensures CLI commands documented for parity features. | +| Screen-reader spot checks | Manual NVDA + VoiceOver scripts | Pre-release checklist | Scenarios: tenant switch, explain drawer, downloads parity copy. | +| Offline smoke | `stella offline kit import` + Playwright sealed-mode run | Prior to Offline Kit cut | Validates offline banners, disabled actions, keyboard flows without Authority. | + +Accessibility QA (CONSOLE-QA-23-402) tracks failing scenarios via Playwright snapshots and publishes reports in the Downloads parity channel (`kind = "parity.report"` placeholder until CLI parity CI lands). + +--- + +## 6 · Offline & Internationalisation Considerations + +- Offline mode surfaces staleness badges and disables remote-only palette entries; keyboard focus skips disabled controls. +- Saved shortcuts, presets, and remaps serialise into Offline Kit bundles so operators can restore preferences post-import. +- Locale switching (future feature flag) will load translations at runtime; ensure ARIA labels use i18n tokens rather than hard-coded strings. +- For sealed installs, guidance panels include CLI equivalents (`stella auth fresh-auth`, `stella runs export`) to unblock tasks when Authority is unavailable. + +--- + +## 7 · Compliance Checklist + +- [ ] Keyboard shortcut matrix validated (default + remapped) and documented. +- [ ] Screen-reader pass recorded for tenant switch, Explain drawer, Downloads copy-to-clipboard. +- [ ] Colour tokens audited; contrast reports stored with release artifacts. +- [ ] Automated a11y pipelines (Storybook axe, Playwright a11y) green; failures feed the `#console-qa` channel. +- [ ] Offline kit a11y smoke executed before publishing each bundle. +- [ ] CLI parity gaps logged in `/docs/cli-vs-ui-parity.md`; UI callouts reference fallback commands until parity closes. +- [ ] Accessibility Guild sign-off captured in sprint log and release notes reference this guide. +- [ ] References cross-checked (`/docs/ui/navigation.md`, `/docs/ui/downloads.md`, `/docs/security/console-security.md`, `/docs/observability/ui-telemetry.md`). + +--- + +## 8 · References + +- `/docs/ui/navigation.md` – shortcut definitions, URL schema. +- `/docs/ui/downloads.md` – CLI parity and offline copy workflows. +- `/docs/ui/console-overview.md` – tenant model, filter behaviours. +- `/docs/security/console-security.md` – security metrics and DPoP/fresh-auth requirements. +- `/docs/observability/ui-telemetry.md` – telemetry metrics mapped to accessibility features. +- `/docs/cli-vs-ui-parity.md` – parity status per console feature. +- `CONSOLE-QA-23-402` – Accessibility QA backlog (Playwright + manual checks). +- `CONSOLE-FEAT-23-102` – Design tokens & theming delivery. + +--- + +*Last updated: 2025-10-28 (Sprint 23).* + diff --git a/docs/airgap/EPIC_16_AIRGAP_MODE.md b/docs/airgap/EPIC_16_AIRGAP_MODE.md deleted file mode 100644 index 3581e835..00000000 --- a/docs/airgap/EPIC_16_AIRGAP_MODE.md +++ /dev/null @@ -1,429 +0,0 @@ -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 16: Air‑Gapped Mode - -**Short name:** Air‑Gapped Mode -**Primary components:** Web Services API, Console, CLI, Orchestrator, Task Runner, Conseiller (Feedser), Excitator (VEXer), Policy Engine, Findings Ledger, Export Center, Authority & Tenancy, Notifications, Observability & Forensics -**Surfaces:** offline bootstrap, update ingestion via mirror bundles, sealed egress, deterministic jobs, offline advisories/VEX, offline policy packs, offline notifications, evidence exports -**Dependencies:** Export Center, Containerized Distribution, Authority‑Backed Scopes & Tenancy, Observability & Forensics, Policy Studio - -**AOC ground rule reminder:** Conseiller and Excitator aggregate and link advisories/VEX. They never merge or mutate source records. Air‑Gapped Mode must preserve this invariant even when mirroring and importing updates. - ---- - -## 1) What it is - -A fully supported operating profile where StellaOps runs in a disconnected environment with: - -* **Zero external egress** from platform services and jobs. -* **Deterministic inputs** provided via signed, offline **Mirror Bundles** (advisories, VEX, policy packs, vendor feeds, Stella metadata, container images, dashboards). -* **Offline bootstrap** for images and charts, plus reproducible configuration and cryptographically verifiable updates. -* **Graceful feature degradation** with explicit UX: features that require external connectivity are either backed by local artifacts or clearly disabled with an explanation. -* **Auditable import/export** including provenance attestations, evidence bundles, and chain‑of‑custody for all offline exchanges. - -Air‑Gapped Mode is selectable at install time and enforceable at runtime. When enabled, all components operate under an “egress sealed” policy and only consume data from local stores. - ---- - -## 2) Why - -Many users operate in classified, regulated, or high‑sensitivity networks where egress is prohibited. They still need SBOM analysis, policy evaluation, advisory/VEX mapping, and reporting. Air‑Gapped Mode provides the same core outcomes with verifiable offline inputs and explicit operational guardrails. - ---- - -## 3) How it should work - -### 3.1 Modes and lifecycle - -* **Connected Mode:** normal operation; can create Mirror Bundles on a staging host. -* **Sealed Air‑Gapped Mode:** platform enforces no egress. Only local resources are allowed. -* **Transition flow:** - - 1. Prepare an offline **Bootstrap Pack** with all container images, Helm/compose charts, seed database, and initial Mirror Bundle. - 2. Install in the air‑gapped enclave and **seal** egress. - 3. Periodically import new **Mirror Bundles** via removable media. - 4. Export evidence/reports as needed. - -### 3.2 Egress sealing - -* **Static guardrails:** - - * Platform flag `STELLA_AIRGAP=sealed` and database feature flag `env.mode='sealed'`. - * NetworkPolicy/iptables/eBPF deny‑all egress for namespaces/pods except loopback and the internal object store. - * Outbound DNS blocked. - * HTTP clients in code use a single `EgressPolicy` facade. When sealed, it panics on direct network calls and returns a typed error with remediation (“import a Mirror Bundle”). -* **Verification:** `GET /system/airgap/status` returns `sealed: true|false`, current policy hash, and last import timestamp. CLI prints warning if not sealed in declared air‑gapped install. - -### 3.3 Trusted time - -* Air‑gapped systems cannot NTP. Each Mirror Bundle includes a **signed time token** (Roughtime‑style or RFC 3161) from a trusted authority. On import, platform stores `time_anchor` for drift calculations and staleness checks. -* If time drift exceeds policy threshold, UI shows “stale view” badges and some jobs are blocked until a new bundle provides a fresh anchor. - -### 3.4 Mirror Bundles (offline updates) - -* **Content types:** - - * Public advisories (OSV, GHSA, vendor advisories), NVD mappings, CPE/Package metadata. - * VEX statements from vendors/communities. - * Policy packs (templates, baselines, versioned rule sets). - * StellaOps engine metadata and schema migrations. - * Optional: **OCI image set** for platform and recommended runners. - * Optional: dashboards and alert rule packs. -* **Format:** a TUF‑like layout: - - ``` - root.json, snapshot.json, timestamp.json, targets/ - advisories/*.jsonl.zst - vex/*.jsonl.zst - policy/*.tar.zst - images/* (OCI layout or oci-archive) - meta/engine/*.tgz - meta/time-anchor.json (signed) - ``` -* **Integrity & trust:** - - * DSSE‑signed target manifests. - * Root of trust rotated via `root.json` within strict policy; rotation requires manual dual approval in sealed mode. - * Each content artifact has a content digest and a **Merkle root** for the overall bundle. -* **Creation:** in connected networks, `stella mirror create --content advisories,vex,policy,images --since 2025-01-01 --out bundle.tgz`. -* **Import:** in air‑gap, `stella airgap import bundle.tgz`. The importer verifies DSSE, TUF metadata, Merkle root, then writes to local object store and updates catalog tables. -* **Idempotence:** imports are content‑addressed; re‑imports deduplicate. - -### 3.5 Deterministic jobs and sources - -* **Allowed sources:** filesystem, internal object store, tenant private registry, and pre‑approved connectors that don’t require external egress. -* **Disallowed in sealed mode:** remote package registries, web scrapers, outbound webhooks, cloud KMS unless on the enclave network. -* **Runner policy:** the Task Runner verifies job descriptors contain no network calls unless marked `internal:` with allow‑listed destinations. Violations fail at plan time with an explainable error. - -### 3.6 Conseiller and Excitator in air‑gap - -* **Conseiller (Feedser):** ingests advisories only from imported bundles or tenant local feeds. It preserves source identities and never merges. Linkage uses bundle‑provided cross‑refs and local heuristics. -* **Excitator (VEXer):** imports VEX records as‑is, links them to components and advisories, and records the origin bundle and statement digests. Consensus Lens (Epic 7) operates offline across the imported sources. - -### 3.7 Policy Engine and Studio - -* Policy packs are versioned and imported via bundles. -* Simulation and authoring work locally. Exports of new or updated policies can be packaged as **Policy Sub‑Bundles** for transfer back to connected environments if needed. -* Engine shows which rules depend on external evidence and how they degrade in sealed mode (e.g., “No external EPSS; using cached percentile from last bundle.”). - -### 3.8 Notifications in sealed mode - -* Default to **local delivery** only: SMTP relay inside enclave, syslog, file sink. -* External webhooks are disabled. -* Notification templates show “air‑gap compliant channel” tags to avoid misconfiguration. - -### 3.9 Observability & Forensics - -* Traces, logs, metrics remain local. -* Evidence Locker supports **portable evidence packages** for cross‑domain transfer: `stella forensic snapshot create --portable`. -* Importing an evidence bundle in another enclave verifies signatures and maintains chain‑of‑custody. - -### 3.10 Console and CLI behavior - -* Console shows a prominent **Air‑Gapped: Sealed** badge with last import time and staleness indicators for advisories, VEX, and policy packs. -* CLI commands gain `--sealed` awareness: any operation that would egress prints a refusal with remediation suggesting the appropriate import. - -### 3.11 Multi‑tenant and scope - -* Tenancy works unchanged. Bundle imports can target: - - * `--tenant-global`: shared catalogs (advisories, VEX, policy baselines). - * `--tenant=`: tenant‑specific content (e.g., private advisories). -* Authority scopes gain `airgap:import`, `airgap:status:read`, `airgap:seal` (admin‑only). - -### 3.12 Feature degradation matrix - -* **AI Assistant:** offline variants use local models if installed; otherwise feature is disabled with a message. -* **External reputation feeds (e.g., EPSS‑like):** replaced by cached values from the bundle. -* **Container base image lookups:** rely on imported metadata or tenant private registry. - ---- - -## 4) Architecture - -### 4.1 New modules - -* `airgap/controller` - - * Sealing state machine; status API; guardrails wiring into HTTP clients and runner. -* `airgap/importer` - - * TUF/DSSE verification, Merkle validation, object store loader, catalog updater. -* `mirror/creator` - - * Connected‑side builder for bundles; content plug‑ins for advisories/VEX/policy/images. -* `airgap/policy` - - * Enforcement library exposing `EgressPolicy` facade and job plan validators. -* `airgap/time` - - * Time anchor parser, drift checks, staleness annotations. -* `console/airgap` - - * Sealed badge, import UI, staleness dashboards, degradation notices. -* `cli/airgap` - - * `stella airgap seal|status|import|verify` commands; `stella mirror create|verify`. - -### 4.2 Data model additions - -* `airgap_state(id, sealed BOOLEAN, policy_hash TEXT, last_import_at TIMESTAMP, time_anchor JSONB)` -* `bundle_catalog(id, kind ENUM, merkle_root TEXT, dsse_signer TEXT, created_at TIMESTAMP, imported_at TIMESTAMP, scope ENUM('global','tenant'), tenant_id NULLABLE, labels JSONB)` -* `bundle_items(bundle_id, path TEXT, sha256 TEXT, size BIGINT, type TEXT, meta JSONB)` -* `import_audit(id, bundle_id, actor, tenant_scope, verify_result, trace_id, created_at)` - -RLS: tenant‑scoped rows when `scope='tenant'`; global rows readable only with `stella:airgap:status:read`. - -### 4.3 Storage layout - -Object store paths: - -``` -tenants/_global/mirror//targets/... -tenants//mirror//targets/... -tenants/_global/images//... -``` - -Evidence locker remains separate. Imported images use **OCI layout** for local registry sync. - -### 4.4 Message topics - -* `stella..airgap.imported` with bundle metadata. -* `stella..airgap.staleness` periodic events emitted for UX. -* `stella..policy.degraded` when rules fall back due to sealed mode. - ---- - -## 5) APIs and contracts - -### 5.1 Status and control - -* `GET /system/airgap/status` → `{ sealed, policy_hash, last_import_at, time_anchor, drift_seconds, staleness: { advisories_days, vex_days, policy_days } }` -* `POST /system/airgap/seal` → seals environment; requires `stella:airgap:seal#tenant/`. -* `POST /system/airgap/unseal` → only allowed if installed mode is not declared “permanently sealed” at bootstrap. Typically disabled. - -### 5.2 Import & verify - -* `POST /airgap/import` multipart or file reference → runs verify, writes catalog, returns bundle summary and warnings. -* `POST /airgap/verify` dry‑run verification returning DSSE/TUF and Merkle results. -* `GET /airgap/bundles` list imported bundles with filters. - -### 5.3 Conseiller/Excitator sources - -* `POST /feeds/register` supports `kind=mirror` with `bundle_id` and paths; disallowed to point to external URLs in sealed mode. -* `GET /feeds/status` shows per‑source staleness and last artifact version. - -### 5.4 Errors - -Standardized sealed‑mode error: - -``` -{ - "code": "AIRGAP_EGRESS_BLOCKED", - "message": "Egress is sealed. Import a Mirror Bundle with advisories.", - "remediation": "Run: stella airgap import bundle.tgz", - "trace_id": "..." -} -``` - ---- - -## 6) Documentation changes - -Create or update: - -1. `/docs/airgap/overview.md` - - * Modes, lifecycle, responsibilities, threat model, what degrades. -2. `/docs/airgap/bootstrap.md` - - * Offline Bootstrap Pack creation, validation, install steps for Helm/compose, local registry seeding. -3. `/docs/airgap/mirror-bundles.md` - - * Bundle format, DSSE/TUF/Merkle, signed time, creation on connected host, import in sealed environment, rotation of roots. -4. `/docs/airgap/sealing-and-egress.md` - - * Network policies, EgressPolicy facade, runner validation, verifying sealed status. -5. `/docs/airgap/staleness-and-time.md` - - * Time anchor, drift, staleness budgets and UI behavior. -6. `/docs/airgap/operations.md` - - * Periodic update cadence, runbooks, failure scenarios, disaster recovery. -7. `/docs/airgap/degradation-matrix.md` - - * Feature map: available, degraded, disabled; with remediation. -8. `/docs/console/airgap.md` - - * Status badges, import wizard, staleness indicators. -9. `/docs/cli/airgap.md` - - * Commands, examples, exit codes. -10. `/docs/security/trust-and-signing.md` - -* Roots of trust, key rotation, DSSE, TUF model. - -11. `/docs/dev/airgap-contracts.md` - -* EgressPolicy usage, testing patterns, sealed‑mode CI gates. - -Add the banner at the top of each page: - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Implementation plan - -### Phase 1 — Foundations - -* Add `airgap/controller` with sealed state and status API. -* Integrate `EgressPolicy` facade in all outbound network call sites. -* Provide default NetworkPolicy/iptables templates and Helm values to block egress. -* Console shows sealed badge and status. - -### Phase 2 — Mirror Bundles - -* Implement `mirror/creator` in connected mode with content plug‑ins. -* Implement `airgap/importer` with DSSE/TUF/Merkle verification and catalog updates. -* Export Center gains **Mirror bundle** build and verify commands (connected side). - -### Phase 3 — Deterministic jobs - -* Add job plan validation in the Task Runner. -* Restrict sources in sealed mode. -* Conseiller/Excitator add “mirror source” adapters. - -### Phase 4 — Staleness and time - -* Parse time anchors; enforce staleness budgets; add UI indicators and task refusal when budgets exceeded. -* Notifications for expiring anchors. - -### Phase 5 — Degradation matrix and UX - -* Wire feature flags and fallbacks in Console and APIs. -* Improve error messages with remediation guidance. - -### Phase 6 — Evidence portability - -* Portable evidence packages: export/import with full verification. -* Document cross‑domain workflows. - ---- - -## 8) Engineering tasks - -**Air‑gap controller and sealing** - -* [ ] Implement `airgap/controller` with persistent state and RBAC. -* [ ] Add `GET /system/airgap/status`, `POST /system/airgap/seal`. -* [ ] Provide cluster egress templates for Kubernetes and for docker‑compose. -* [ ] Instrument startup checks to refuse running in sealed mode if egress rules aren’t applied. - -**EgressPolicy integration** - -* [ ] Create `pkg/egress` facade and replace all direct HTTP client constructions in services. -* [ ] Add linter rule and CI check forbidding raw `http.NewClient` in server code. -* [ ] Add unit tests for sealed and unsealed behavior. - -**Mirror bundles** - -* [ ] Implement TUF/DSSE verifiers and Merkle root builder. -* [ ] Build content plug‑ins: advisories, VEX, policy packs, images. -* [ ] Write `bundle_catalog` and `bundle_items` tables with RLS. -* [ ] CLI: `stella mirror create|verify`, `stella airgap import|verify`. - -**Conseiller/Excitator** - -* [ ] Add mirror adapters for read‑only ingestion from bundle paths. -* [ ] Persist source digests and bundle IDs on each linked record. -* [ ] Unit tests to ensure no merge behavior is introduced by bundle ingestion. - -**Policy Engine & Studio** - -* [ ] Accept policy packs from bundles; track `policy_version` and `bundle_id`. -* [ ] Add degradation notices for rules requiring external reputation; provide cached fallbacks. - -**Task Runner & Orchestrator** - -* [ ] Plan‑time validation against network calls; add `internal:` allow‑list mapping. -* [ ] Emit sealed‑mode violations to Timeline with remediation text. - -**Console** - -* [ ] Status panel: sealed badge, last import, staleness meters. -* [ ] Import wizard with verify results and catalog diff preview. -* [ ] Degradation matrix UI and contextual tooltips. - -**Observability & Forensics** - -* [ ] Mark sealed mode in telemetry attributes. -* [ ] Add portable evidence package export/import; verify on read. - -**Authority & Tenancy** - -* [ ] New scopes: `airgap:seal`, `airgap:import`, `airgap:status:read`. -* [ ] Audit import actions with actor and trace ID. - -**Docs** - -* [ ] Author all pages listed in section 6, include signed‑time workflow diagrams. -* [ ] Insert banner statement in each page. - -**Testing** - -* [ ] Sealed‑mode e2e: attempt egress; ensure refusal and remediation. -* [ ] Bundle import e2e: corrupt DSSE, wrong root, tampered artifact → rejected. -* [ ] Performance: large advisory bundle import within target time (see Acceptance). -* [ ] Time drift scenarios and staleness budget enforcement. -* [ ] Regression: ensure AOC rules unchanged in sealed mode. - ---- - -## 9) Feature changes required in other components - -* **Export Center:** add mirror bundle export profile, signed‑time token inclusion, and portable evidence packages. -* **Notifications:** remove external webhooks by default in sealed mode; add local SMTP/syslog sinks. -* **CLI Parity:** ensure all admin and import operations are exposed; add sealed‑mode safety prompts. -* **Containerized Distribution:** ship **Bootstrap Pack** that includes all images and charts in a single oci‑archive set with index manifest. -* **Observability:** disable remote exporters; include local dashboards; mark sealed mode in UI. -* **Policy Studio:** enable offline authoring and export of policy sub‑bundles. -* **VEX Consensus Lens:** ensure it operates solely on imported VEX statements; highlight coverage vs. stale. - -> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 10) Acceptance criteria - -* Environment can be **sealed** and verified via API, CLI, and network policies. -* Import of a valid Mirror Bundle succeeds; DSSE, TUF, and Merkle validations recorded in `import_audit`. -* Conseiller and Excitator operate only on imported sources; linkage reflects original source identities. -* Policy packs are importable and versioned; rules that depend on external evidence show clear degradation. -* Large bundle (e.g., 8–12 GB with images) imports in under 20 minutes on SSD storage and indexes advisories in under 5 minutes on a 4‑core node. -* Console displays sealed badge, last import, staleness, and degradation matrix. -* Attempted egress in sealed mode fails with `AIRGAP_EGRESS_BLOCKED` and remediation. -* Portable evidence packages export and verify across separate enclaves. -* All changes documented with the banner statement. - ---- - -## 11) Risks and mitigations - -* **Key management complexity:** rotate TUF roots with dual‑control workflow and explicit docs; fail‑safe to previous root if rotation bundle absent. -* **Staleness risk:** enforce budgets and block risk‑critical jobs when expired; provide monitoring and notifications for impending staleness. -* **Operator error during import:** dry‑run verification, diff preview of catalog changes, and ability to roll back via content address. -* **Hidden egress paths:** CI lints and runtime guardrails; network policies enforced at cluster layer. -* **Bundle size bloat:** Zstandard compression, delta bundles, and selective content flags for creation. - ---- - -## 12) Philosophy - -* **Predictable over perfect:** deterministic, explainable results beat unknown “live” results in sensitive networks. -* **Trust is earned:** every offline exchange is signed, verifiable, and auditable. -* **Degrade transparently:** when features reduce capability, explain it and guide remediation. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/airgap/airgap-mode.md b/docs/airgap/airgap-mode.md new file mode 100644 index 00000000..909f125d --- /dev/null +++ b/docs/airgap/airgap-mode.md @@ -0,0 +1,71 @@ +# Air-Gapped Mode Playbook + +> Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +## Overview + +Air-Gapped Mode is the supported operating profile for deployments with **zero external egress**. All inputs arrive via signed mirror bundles, and every surface (CLI, Console, APIs, schedulers, scanners) operates under sealed-network constraints while preserving Aggregation-Only Contract invariants. + +- **Primary components:** Web Services API, Console, CLI, Orchestrator, Task Runner, Conseiller (Feedser), Excitator (VEXer), Policy Engine, Findings Ledger, Export Center, Authority & Tenancy, Notifications, Observability & Forensics. +- **Surfaces:** offline bootstrap, mirror ingestion, deterministic jobs, offline advisories/VEX/policy packs/notifications, evidence exports. +- **Dependencies:** Export Center, Containerized Distribution, Authority-backed scopes & tenancy, Observability & Forensics, Policy Studio. + +## Guiding principles + +1. **Zero egress:** all outbound network calls are disabled unless explicitly allowed. Any feature requiring online data must degrade gracefully with clear UX messaging. +2. **Deterministic inputs:** the platform accepts only signed Mirror Bundles (advisories, VEX, policy packs, vendor feeds, images, dashboards). Bundles carry provenance attestations and chain-of-custody manifests. +3. **Auditable exchange:** every import/export records provenance, signatures, and operator identity. Evidence bundles and reports remain verifiable offline. +4. **Aggregation-Only Contract compliance:** Conseiller and Excitator continue to aggregate without mutating source records, even when ingesting mirrored feeds. +5. **Operator ergonomics:** offline bootstrap, upgrade, and verification steps are reproducible and scripted. + +## Lifecycle & modes + +| Mode | Description | Tooling | +| --- | --- | --- | +| Connected | Standard deployment with online feeds. Operators use Export Center to build mirror bundles for offline environments. | `stella export bundle create --profile mirror:full` | +| Staging mirror | Sealed host that fetches upstream feeds, runs validation, and signs mirror bundles. | Export Center, cosign, bundle validation scripts | +| Air-gapped | Production cluster with egress sealed, consuming validated bundles, issuing provenance for inward/outward transfers. | Mirror import CLI, sealed-mode runtime flags | + +### Installation & bootstrap + +1. Prepare mirror bundles (images, charts, advisories/VEX, policy packs, dashboards, telemetry configs). +2. Transfer bundles via approved media and validate signatures (`cosign verify`, bundle manifest hash). +3. Deploy platform using offline artefacts (`helm install --set airgap.enabled=true`), referencing local registry/object storage. + +### Updates + +1. Staging host generates incremental bundles (mirror delta) with provenance. +2. Offline site imports bundles via the CLI (`stella airgap import --bundle`) and records chain-of-custody. +3. Scheduler triggers replay jobs with deterministic timelines; results remain reproducible across imports. + +## Component responsibilities + +| Component | Offline duties | +| --- | --- | +| Export Center | Produce full/delta mirror bundles, signed manifests, provenance attestations. | +| Authority & Tenancy | Provide offline scope enforcement, short-lived tokens, revocation via local CRLs. | +| Conseiller / Excitator | Ingest mirrored advisories/VEX, enforce AOC, versioned observations. | +| Policy Engine & Findings Ledger | Replay evaluations using offline feeds, emit explain traces, support sealed-mode hints. | +| Notifications | Deliver locally via approved channels (email relay, webhook proxies) or queue for manual export. | +| Observability | Collect metrics/logs/traces locally, generate forensic bundles for external analysis. | + +## Operational guardrails + +- **Network policy:** enforce allowlists (`airgap.egressAllowlist=[]`). Any unexpected outbound request raises an alert. +- **Bundle validation:** double-sign manifests (bundle signer + site-specific cosign key); reject on mismatch. +- **Time synchronization:** rely on local NTP or manual clock audits; many signatures require monotonic time. +- **Key rotation:** plan for offline key ceremonies; Export Center and Authority document rotation playbooks. +- **Incident response:** maintain scripts for replaying imports, regenerating manifests, and exporting forensic data without egress. + +## Testing & verification + +- Integration tests mimic offline installs by running with `AIRGAP_ENABLED=true` in CI. +- Mirror bundles include validation scripts to compare hash manifests across staging and production. +- Sealed-mode smoke tests ensure services fail closed when attempting egress. + +## References + +- Export workflows: `docs/modules/export-center/overview.md` +- Policy sealed-mode hints: `docs/policy/overview.md` +- Observability forensic bundles: `docs/modules/telemetry/architecture.md` +- Runtime posture enforcement: `docs/modules/zastava/operations/runtime.md` diff --git a/docs/aoc/aoc-guardrails.md b/docs/aoc/aoc-guardrails.md index 09340158..3654d60b 100644 --- a/docs/aoc/aoc-guardrails.md +++ b/docs/aoc/aoc-guardrails.md @@ -1,13 +1,13 @@ -# Aggregation-Only Contract (AOC) Guardrails - -The Aggregation-Only Contract keeps ingestion services deterministic and policy-neutral. Use these checkpoints whenever you add or modify backlog items: - -1. **Ingestion writes raw facts only.** Concelier and Excititor append immutable observations/linksets. No precedence, severity, suppression, or "safe fix" hints may be computed at ingest time. -2. **Derived semantics live elsewhere.** Policy Engine overlays, Vuln Explorer composition, and downstream reporting layers attach severity, precedence, policy verdicts, and UI hints. -3. **Provenance is mandatory.** Every ingestion write must include original source metadata, digests, and signing/provenance evidence when available. Reject writes lacking provenance. -4. **Deterministic outputs.** Given the same inputs, ingestion must produce identical documents, hashes, and event payloads across reruns. -5. **Guardrails everywhere.** Roslyn analyzers, schema validators, and CI smoke tests should fail builds that attempt forbidden writes. - -For detailed roles and ownership boundaries, see `AGENTS.md` at the repo root and the module-specific `ARCHITECTURE_*.md` dossiers. - -Need the full contract? Read the [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) for schemas, error codes, and migration guidance. +# Aggregation-Only Contract (AOC) Guardrails + +The Aggregation-Only Contract keeps ingestion services deterministic and policy-neutral. Use these checkpoints whenever you add or modify backlog items: + +1. **Ingestion writes raw facts only.** Concelier and Excititor append immutable observations/linksets. No precedence, severity, suppression, or "safe fix" hints may be computed at ingest time. +2. **Derived semantics live elsewhere.** Policy Engine overlays, Vuln Explorer composition, and downstream reporting layers attach severity, precedence, policy verdicts, and UI hints. +3. **Provenance is mandatory.** Every ingestion write must include original source metadata, digests, and signing/provenance evidence when available. Reject writes lacking provenance. +4. **Deterministic outputs.** Given the same inputs, ingestion must produce identical documents, hashes, and event payloads across reruns. +5. **Guardrails everywhere.** Roslyn analyzers, schema validators, and CI smoke tests should fail builds that attempt forbidden writes. + +For detailed roles and ownership boundaries, see `AGENTS.md` at the repo root and the module-specific dossiers under `docs/modules//architecture.md`. + +Need the full contract? Read the [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) for schemas, error codes, and migration guidance. diff --git a/docs/api/EPIC_17_SDKS_OPENAPI.md b/docs/api/EPIC_17_SDKS_OPENAPI.md deleted file mode 100644 index 8dc0d548..00000000 --- a/docs/api/EPIC_17_SDKS_OPENAPI.md +++ /dev/null @@ -1,357 +0,0 @@ -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 17: SDKs and OpenAPI Docs - -**Short name:** SDKs & OpenAPI -**Primary components:** API Gateway, Web Services, Policy Engine, Conseiller (Feedser), Excitator (VEXer), Orchestrator, Findings Ledger, Export Center, Authority & Tenancy, Console, CLI -**Surfaces:** OpenAPI 3.1 contracts, language SDKs (TS/Node, Python, Go, Java, C#), dev portal, examples, mock server, conformance tests, changelogs, versioning, deprecations -**Dependencies:** Authority‑Backed Scopes & Tenancy, CLI Parity, Export Center, Notifications Studio, Air‑Gapped Mode, Observability - -**AOC ground rule reminder:** Conseiller and Excitator aggregate and link advisories/VEX. They never merge or mutate source records. SDKs must preserve this invariant and expose source identity in all models. - ---- - -## 1) What it is - -A contract‑first program that standardizes StellaOps’ APIs with OpenAPI 3.1 and ships official, versioned SDKs for popular languages. It includes: - -* A single **source‑of‑truth OpenAPI** for each service and a canonical aggregate spec. -* **Generated SDKs** with idiomatic ergonomics, retries, auth helpers, pagination cursors, streaming downloads, and typed error envelopes. -* A **developer portal** with interactive reference, runnable examples, and “copy‑curl” snippets. -* **Mock server & conformance tests** so changes are validated against the contract before code ships. -* **Versioning & deprecation policy**, automated changelogs, and notification hooks. -* **Air‑gapped bundles** of docs and SDKs for disconnected environments. - -Net result: partners and internal teams integrate quickly without reverse‑engineering request bodies from error logs. - ---- - -## 2) Why - -* Reduce friction and support load with a single, accurate contract. -* Make the platform extensible: third parties can build automation, dashboards, and policy pipelines without trawling source code. -* Enforce stability: contract linting and backwards‑compat checks prevent accidental breakage. -* Bring CLI and Console parity to programmatic users through first‑class clients. - ---- - -## 3) How it should work - -### 3.1 Source of truth and layout - -* Each service owns a **module-scoped OAS** file: `src/Api/StellaOps.Api.OpenApi//openapi.yaml`. - * Authority authentication/token surface now lives at `src/Api/StellaOps.Api.OpenApi/authority/openapi.yaml`, covering `/token`, `/introspect`, `/revoke`, and `/jwks` flows with examples and scope catalog metadata. -* An aggregate spec `src/Api/StellaOps.Api.OpenApi/stella.yaml` is produced by build tooling that composes per-service specs, resolves `$ref`s, and validates cross-service schemas. -* JSON Schema dialect: 2020‑12 (OpenAPI 3.1). No vendor‑specific features for core models. -* Every response and error has at least one **validated example**. - -### 3.2 API conventions (normative) - -* **Paths:** `/v1/{resource}`, plural nouns. Subresources use `/v1/resources/{id}/subresources`. -* **Identifiers:** `id` fields are ULID/UUIDv7 as strings. -* **Pagination:** cursor‑based: `?cursor=&limit=`, response envelope includes `next_cursor`. -* **Sorting/filtering:** `?sort=field:asc|desc`, `?filter[field]=op:value` with documented operators. -* **Idempotency:** POST operations that create or mutate accept `Idempotency-Key`. -* **Errors:** single envelope: - - ```json - { - "error": { - "code": "STRING_CODE", - "message": "human friendly", - "details": { "field": "value" }, - "trace_id": "..." - } - } - ``` - - Standard codes include `AIRGAP_EGRESS_BLOCKED`, `POLICY_VIOLATION`, `NOT_FOUND`, `RATE_LIMITED`. -* **Auth:** OAuth2 client credentials and PAT. Scopes are explicit (see 14: Authority‑Backed Scopes). Tenancy via claims; optional override header: `X-Stella-Scope: tenant/` if the token permits delegation. -* **Content negotiation:** JSON only for request/response unless endpoint is a stream or file download (`application/octet-stream`). -* **Long‑running operations:** either webhooks (if enabled) or polling via `operation_id` resource. - -### 3.3 Versioning and deprecation - -* **SemVer** for the aggregate API: `v1`, `v2` in base path. -* Backwards‑compatible changes allowed in minor versions (add fields, new optional params). -* Breaking changes require new major version and coexistence for a **deprecation window** (min 12 months) with: - - * Deprecation headers: `Deprecation: true`, `Sunset: `, `Link: `. - * Portal banners and Notifications Studio broadcast. - -### 3.4 Governance and linting - -* Enforce naming, pagination, error envelope, and example requirements via an OAS linter. -* CI gate: no PR merges if OAS validation fails or coverage < 100% for operation examples. -* **Compatibility check:** diff new OAS vs previous release, fail on breaking changes unless explicitly flagged. - -### 3.5 SDK generation - -* Initial languages: **TypeScript/Node**, **Python**, **Go**, **Java**. C# and Rust are follow‑ups. -* Generated via a stable, reproducible toolchain. Post‑generation patches are applied by templates, not hand edits. -* **Capabilities:** - - * Auth helpers: PAT and OAuth2. - * Retries with decorrelated jitter and `Retry‑After` respect. - * Pluggable HTTP transport for proxies and air‑gapped environments. - * Binary download helpers and upload helpers for multipart endpoints. - * Paginators that yield items and handle `next_cursor`. - * Rich error types mapping `error.code` to language enums. - * Telemetry hooks (before/after request callbacks). -* **Packaging:** - - * TS: npm package with ESM and CJS builds, types included. - * Python: PyPI package, Pydantic‑friendly models, type hints. - * Go: module with context‑aware methods and `io.Reader` streaming. - * Java: Maven coordinates, builder pattern, OkHttp/HTTP client provider. -* **Versioning:** SDK major matches API major. Minor/patch track generator changes only. - -### 3.6 Dev portal and artifacts - -* **Reference docs** auto‑built from the aggregate OAS with searchable nav, schema diagrams, and example blocks. -* **Try‑it** panel wired to the sandbox environment (disabled in air‑gap). -* **Download center:** links to SDKs, changelogs, and Postman/HTTP collection exports. -* **.well‑known discovery:** `GET /.well-known/openapi` returns the canonical spec. - -### 3.7 Conformance testing - -* **Mock server** generated from OAS for contract tests. -* **Replay tests**: real services are validated against the OAS via request/response capture; deviations fail CI. -* **Golden examples**: every endpoint has recorded examples exercised in tests. - -### 3.8 Air‑Gapped support - -* Export Center can build a **Docs & SDKs bundle**: `stella export devportal --offline`, including HTML docs, specs, and packages. -* SDKs avoid network discovery and accept explicit base URLs; no auto‑updates. - -### 3.9 Domain‑specific notes - -* **Conseiller/Excitator:** models expose `source_id`, `source_type`, `source_digest`. SDKs never hide source multiplicity. -* **Policy Engine:** policy documents are versioned; SDK supports dry‑run/simulate endpoints with structured explanations. -* **Findings Ledger:** paginated listing includes stable, filterable fields for evidence export. - ---- - -## 4) Architecture - -### 4.1 New modules - -* `src/Api/StellaOps.Api.OpenApi/*` per service and aggregate composer -* `src/Api/StellaOps.Api.Governance` OAS linter rules and compatibility checker -* `src/Sdk/StellaOps.Sdk.Generator` codegen drivers, post‑processing templates, smoke tests -* `src/Sdk/StellaOps.Sdk.Release` packaging, signing, publishing -* `src/DevPortal/StellaOps.DevPortal.Site` static generator and assets -* `test/contract` mock server config, golden examples -* `src/ExportCenter/StellaOps.ExportCenter.DevPortalOffline` bundler - -### 4.2 Build flow - -1. Validate per‑service specs → compose aggregate → lint → compatibility diff. -2. Generate SDKs → build → run language‑level tests → publish to internal registry. -3. Build dev portal and publish. -4. Optionally build offline bundle. - -### 4.3 Runtime contracts - -* `GET /.well-known/openapi` per service and at the gateway. -* All services embed `x-stella-service` and `x-stella-version` extensions for traceability. - ---- - -## 5) APIs and contracts (select) - -* **Discovery**: `GET /.well-known/openapi` → JSON or YAML. -* **Errors**: standard envelope (see 3.2). -* **Rate limits**: expose `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`. -* **Operations**: long‑running ops expose `operation_id` and `status` via `GET /v1/operations/{id}`. - ---- - -## 6) Documentation changes - -Create or update: - -1. `/docs/api/overview.md` - - * API surface, auth, tenancy, pagination, idempotency, rate limits. -2. `/docs/api/conventions.md` - - * Path, naming, errors, filters, sorting, examples. -3. `/docs/api/versioning.md` - - * SemVer policy, deprecation windows, headers, migration playbooks. -4. `/docs/api/reference/` - - * Auto‑generated OAS site; link into service pages. -5. `/docs/sdks/overview.md` - - * Supported languages, install, hello‑world, retry/auth patterns. -6. `/docs/sdks/typescript.md`, `/python.md`, `/go.md`, `/java.md` - - * Language‑specific guides, snippets, paginator usage, streaming. -7. `/docs/devportal/publishing.md` - - * Build pipeline, offline bundle steps. -8. `/docs/contributing/api-contracts.md` - - * How to edit OAS, lint rules, compatibility checks, examples. -9. `/docs/testing/contract-testing.md` - - * Mock server, golden examples, replay tests. -10. `/docs/security/auth-scopes.md` - - * OAuth2, PAT, scope mapping, tenancy header. -11. `/docs/airgap/devportal-offline.md` - - * Air‑gapped docs and SDK bundle usage. - -Add the banner at the top of each page: - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Implementation plan - -### Phase 1 — Foundations - -* Establish per‑service OAS skeletons and the aggregate composer. -* Introduce linting and compatibility checks in CI. -* Define the standard error envelope and migrate services. - -### Phase 2 — Reference & discovery - -* Implement `/.well-known/openapi` for gateway and services. -* Build the dev portal with search, schema diagrams, and examples. - -### Phase 3 — SDKs (TS, Python, Go, Java) - -* Implement generator drivers and templates. -* Publish alpha packages internally; integrate in CLI and Console integration tests. -* Add paginators, retries, auth helpers, and streaming. - -### Phase 4 — Conformance & examples - -* Wire mock server into PR CI. -* Record golden example fixtures and replay tests against staging. -* Automate example extraction into docs. - -### Phase 5 — Release automation & deprecation - -* Automate changelogs from OAS diffs. -* Notifications Studio integration for API deprecations. -* Offline dev portal bundle through Export Center. - -### Phase 6 — Follow‑ups - -* C# and Rust SDKs, Postman/HTTP collections, sample apps repo. - ---- - -## 8) Engineering tasks - -**OAS & governance** - -* [ ] Create `src/Api/StellaOps.Api.OpenApi//openapi.yaml` for all services with minimal paths and shared components. -* [ ] Implement aggregate composer and `$ref` resolver. -* [ ] Add CI job: lint, validate, compatibility diff; block merges on failure. -* [ ] Migrate all endpoints to standard error envelope and provide examples. - -**Discovery & portal** - -* [ ] Implement `GET /.well-known/openapi` at service and gateway. -* [ ] Build dev portal: nav, search, schema viewer, try‑it (non‑prod), copy‑curl. -* [ ] Add version selector for v1/v2 specs. - -**SDKs** - -* [ ] Generator driver with pinned templates; forbid manual edits in generated folders. -* [ ] TS SDK: ESM/CJS build, tree‑shaking, paginator, middleware hooks. -* [ ] Python SDK: async and sync clients, type hints, file upload/download helpers. -* [ ] Go SDK: context‑first API, streaming, error type mapping. -* [ ] Java SDK: builder pattern, HTTP client provider abstraction. -* [ ] Common: retries, `Retry‑After` handling, idempotency key helper, auth helpers, telemetry hooks. -* [ ] Language‑specific tests and smoke examples. - -**Conformance** - -* [ ] Mock server config with operation examples. -* [ ] Replay tests against staging; fail on schema drift. -* [ ] Golden example extraction pipeline. - -**Air‑Gapped** - -* [ ] Export Center job: `devportal --offline` producing HTML docs, specs, and package artifacts. -* [ ] SDKs accept explicit base URLs; disable online discovery. - -**Authority & Tenancy** - -* [ ] Document scopes per endpoint in OAS (`securitySchemes` + `security` blocks). -* [ ] Implement optional `X-Stella-Scope` override with validation. - -**Release automation** - -* [ ] Version bump tooling for OAS and SDKs; SemVer aligned. -* [ ] Auto‑generate `CHANGELOG.md` from OAS diffs. -* [ ] Publish to registries with signed artifacts and provenance. - -**Docs** - -* [ ] Author all pages listed in section 6; embed code snippets pulled from tested examples. -* [ ] Insert banner statement in each page. - -**Testing** - -* [ ] Contract tests in PR CI; 100% operation coverage with at least one example. -* [ ] Language SDK integration tests against mock server and staging. -* [ ] Backwards‑compat test suite comparing last N releases. - ---- - -## 9) Feature changes required in other components - -* **Web Services:** unify on error envelope, pagination, idempotency handling, and deprecation headers. -* **CLI:** consume the official TS or Go SDK instead of bespoke HTTP calls; this enforces parity. -* **Console:** use SDKs for backend calls where appropriate; helps dogfood the clients. -* **Export Center:** add `devportal --offline` and package signing. -* **Observability:** include `x-stella-service` and API version attributes in spans; trace IDs mirrored in error responses. -* **Notifications Studio:** templates for API deprecations and SDK updates. -* **Air‑Gapped Mode:** ship offline dev portal and SDKs bundle; console disables try‑it. - -> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 10) Acceptance criteria - -* Aggregate OpenAPI validates, lints cleanly, and covers 100% of public endpoints with examples. -* `/.well-known/openapi` available at gateway and service level. -* Dev portal builds with search, example blocks, and version selector. -* TS/Python/Go/Java SDKs publish successfully; each has paginators, retries, auth helpers, streaming, and typed errors. -* CLI integrations pass using SDKs. -* Contract tests run in PR CI; schema drift causes failures. -* Deprecation headers and Notifications Studio flow proven in a staged deprecation. -* Offline dev portal bundle exports and renders in a sealed environment. - ---- - -## 11) Risks and mitigations - -* **Spec drift vs code reality:** mock‑first development and replay tests keep services aligned with OAS. -* **Generator churn:** pin generator and templates; only update via planned minor releases. -* **Breaking changes under pressure:** enforce compatibility gate and documented exception process. -* **SDK ergonomics mismatch:** run language‑native design reviews with maintainers before GA. -* **Air‑gapped constraints:** prebuild full offline bundles; avoid dynamic CDN assets in docs. - ---- - -## 12) Philosophy - -* **Contract first, code second.** The spec is the product; servers and SDKs are implementations. -* **Stability over cleverness.** Boring, predictable APIs beat “magical” behavior. -* **Truth preservation.** Never hide or merge advisory/VEX sources; surface provenance everywhere. -* **Automation everywhere.** Humans shouldn’t manually edit generated code or publish packages. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/api/sdk-openapi-program.md b/docs/api/sdk-openapi-program.md new file mode 100644 index 00000000..66d87d3c --- /dev/null +++ b/docs/api/sdk-openapi-program.md @@ -0,0 +1,51 @@ +# SDK & OpenAPI Program + +> Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +## Overview + +The SDK & OpenAPI program delivers canonical OpenAPI 3.1 contracts for every Stella Ops surface, plus officially supported SDKs (TypeScript/Node, Python, Go, Java, C#). It ensures backwards-compatible evolution, documentation, and offline availability. + +- **Primary components:** API Gateway, Web Services, Policy Engine, Conseiller, Excitator, Orchestrator, Findings Ledger, Export Center, Authority & Tenancy, Console, CLI. +- **Surfaces:** OpenAPI specs, language SDKs, developer portal, examples, mock server, conformance tests, changelog feeds, deprecation notices. +- **Dependencies:** Authority scopes/tenancy, CLI parity, Export Center, Notifications, Air-Gapped Mode, Observability. + +## Program pillars + +1. **Contract-first:** treat OpenAPI specs as the source of truth. CI validates schemas, compatibility, and documentation generation. +2. **SDK parity:** language SDKs cover the same surfaces with deterministic clients, pagination helpers, and typed models mirroring Aggregation-Only Contract semantics. +3. **Version discipline:** semantic versioning for specs and SDKs, release notes, deprecation windows, and automated change alerts via Notifications. +4. **Offline readiness:** specs and SDK bundles ship in Mirror Bundles for air-gapped environments; examples include smoke tests. +5. **Observability:** telemetry around SDK usage, spec download metrics, and error reporting funnels back into product decisions. + +## Deliverables + +| Workstream | Deliverable | +| --- | --- | +| Spec authoring | Unified OpenAPI 3.1 documents per service plus aggregate spec; lint rules; schema registries. | +| SDK generation | Language-specific clients with idiomatic ergonomics, retries, pagination, long-running operation helpers, unit + integration tests. | +| Dev portal | Consolidated documentation, guides, changelog, copy/paste examples, quickstart scripts. | +| Testing | Contract tests against staging, mock server for integration tests, compatibility verification per release. | +| Release ops | Automated CI pipelines, version bump workflows, release notes, deprecation policies. | + +## Guardrails + +- **Aggregation-Only Contract compliance:** SDKs expose raw advisory/VEX objects without hidden merges; all derived fields require explicit Policy Engine calls. +- **Security:** enforce scopes via SDK configuration; redact secrets; support DPoP/mTLS and offline token provisioning. +- **Compatibility:** maintain backwards-compatible paths for at least two minor releases; log warnings on deprecated endpoints. +- **Documentation:** publish examples for common workflows (scan, policy evaluate, export, attestation) with language parity. + +## Roadmap checkpoints + +1. Baseline OpenAPI specs extracted from gateway, validated, and published. +2. TypeScript/Node SDK as pilot, followed by Python and Go. +3. Developer portal launch with SDK docs, quickstarts, and mock server. +4. Offline kit integration (mirror bundles include specs + SDK tarballs). +5. Runtime alerting for breaking changes and dependency vulnerabilities. + +## References + +- API gateway integration: `docs/modules/platform/architecture-overview.md` +- Policy/Findings models: `docs/modules/policy/architecture.md`, `docs/modules/vuln-explorer/architecture.md` +- Export bundle distribution: `docs/modules/export-center/overview.md` +- Offline workflows: `docs/airgap/airgap-mode.md` diff --git a/docs/attestor/EPIC_19_ATTESTOR_CONSOLE.md b/docs/attestor/EPIC_19_ATTESTOR_CONSOLE.md deleted file mode 100644 index 22b74685..00000000 --- a/docs/attestor/EPIC_19_ATTESTOR_CONSOLE.md +++ /dev/null @@ -1,135 +0,0 @@ -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 19: Attestor Console - -**Short name:** Attestor Console -**Primary components:** Attestation Service, Policy Studio, Authority & Tenancy, Export Center, Observability, CLI, StellaOps Console -**Surfaces:** Web UI, REST APIs, CLI, SDKs, docs - -**AOC ground rule reminder:** Conseiller and Excitator only aggregate and link. They never merge sources. Attestations must reference the exact subject digests and their source provenance. No collapsing of distinct advisories or VEX statements. - ---- - -## 1) What it is - -Attestor Console centralizes creation, verification, browsing, and operationalization of software supply chain attestations within StellaOps. It covers build provenance, SBOM attestations, VEX statements, scan results, policy evaluations, risk profile evidence, and custom facts—all signed and verifiable end-to-end. - ---- - -## 2) Why - -Trustworthy pipelines need signed evidence, repeatable verification, explainability, and policy enforcement. Attestor Console weaves attestations into the rest of Stella (AOC, Policy Studio gates, Risk Profiles, Notifications, Export Center) to reduce blind spots and accelerate compliance. - ---- - -## 3) How it should work - -### 3.1 Roles, identities, scopes - -* Subjects: immutable digests for artifacts (images, packages, SBOMs, findings). -* Issuers: identities that sign attestations (builders, scanners, policy engines). -* Scopes: tenant/project/environment context enforced by Authority & Tenancy. - -### 3.2 Payload types - -Supports DSSE envelopes for BuildProvenance v1, SBOMAttestation v1, VEXAttestation v1, ScanResults v1, PolicyEvaluation v1, RiskProfileEvidence v1, and CustomEvidence v1. All payloads include subject, issuer, scope, materials, provenance, policy context, and versioned schemas. - -### 3.3 Envelope & signature model - -DSSE envelopes with multi-signature support, Ed25519/ECDSA keys, KMS/HSM/FIDO2 drivers, transparency log witnesses, and detached payload storage. Identity policies ensure least privilege and traceability. - -### 3.4 Verification pipeline - -Runs at ingest, policy gates, and interactively. Steps: resolve subject, fetch envelopes + witness proofs, validate DSSE structure/signatures, evaluate issuer trust and policies, produce cached verification reports. - -### 3.5 Verification policies - -Policy Studio authored rules covering required evidence types, allowed issuers, freshness, transparency requirements, signature counts, and waivers. Supports scoped overrides and defaults. - -### 3.6 UI workflows - -Evidence Browser, Verification Reports, Chain of Custody Graph, Key & Issuer Management, Attestation Workbench, and Bulk Verification views in Console. - -### 3.7 CLI & SDK - -Commands: `stella attest sign`, `verify`, `list`, `fetch`, `key create/import/rotate/revoke`. SDKs expose Sign/Verify/List/Fetch APIs. - -### 3.8 Data model - -Tables for attestations, issuers, verification reports, transparency index, key store. Indexed by subject digest, type, issuer, and timestamps. - -### 3.9 Storage & air gap - -Store envelopes in CAS object storage; optionally mirror transparency logs. `stella export attestation-bundle` enables offline transfer. Policies can relax witness requirements for sealed environments while logging the gap. - -### 3.10 Observability & security - -Spans, metrics, logs for signing and verification. Private keys never leave KMS/HSM. Revocation/rotation supported. Verification rejects mismatched subjects and ensures AOC invariants for scan/VEX evidence. - -### 3.11 Performance - -Use compressed JSON payloads, cached verification results, batched operations, and concurrency controls. P95 target: 1k envelopes/min on a single worker. - ---- - -## 4) Architecture - -New services (`src/Attestor/StellaOps.Attestor/`), libraries (`src/Attestor/StellaOps.Attestor.Envelope/`, `src/Attestor/StellaOps.Attestor.Types/`, `src/Attestor/StellaOps.Attestor.Verify/`), CLI (`src/Cli/StellaOps.Cli/`), export tooling (`src/ExportCenter/StellaOps.ExportCenter.AttestationBundles/`), and shared KMS providers (`src/__Libraries/StellaOps.Cryptography.Kms/`). REST endpoints documented in OpenAPI. - ---- - -## 5) Documentation changes - -Requires new pages for overview, payloads, policies, workflows, key management, transparency, air gap, console UI, CLI, and updated security invariants, all with the imposed rule banner. - ---- - -## 6) Implementation plan - -Six phases: Foundations; Policies & UI; Scan & VEX support; Transparency & keys; Bulk & air gap; Performance & hardening. - ---- - -## 7) Engineering tasks - -Detailed tasks across envelope/crypto, payload schemas, APIs, Policy Studio integration, Console UI, CLI, transparency, bulk operations, observability, security, docs, and testing. - ---- - -## 8) Feature changes required elsewhere - -Policy Studio (VerificationPolicy), Export Center (attestation bundles), Authority & Tenancy, SBOM/Vulnerability explorers, Notifications, Observability. All must inherit the imposed rule and update docs accordingly. - ---- - -## 9) Acceptance criteria - -Signing and verification for all payloads, policy enforcement, Console views, bulk verification, export/import for air gap, observability coverage, AOC invariants respected, documented OpenAPI endpoints. Tests and performance targets met. - ---- - -## 10) Risks & mitigations - -Key compromise, parsing bugs, policy complexity, transparency outages addressed via rotation workflows, fuzz tests, curated starter policies, and fallback/mirroring strategies. - ---- - -## 11) Philosophy - -Evidence first, scoped identities, cheap verification, portable attestations, truth preservation. - ---- - -## 12) Examples - -Includes abbreviated SBOM attestation and verification report JSON samples illustrating required fields and outcomes. - ---- - -## 13) Cross-epic documentation updates - -Cross-link Attestor docs from Policy Studio, Export Center, Air-Gapped, Observability, Risk Profiles, SBOM Graph, and Vulnerability Explorer pages, maintaining the imposed rule banner. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/cli-vs-ui-parity.md b/docs/cli-vs-ui-parity.md index 0fde684a..5cc259c2 100644 --- a/docs/cli-vs-ui-parity.md +++ b/docs/cli-vs-ui-parity.md @@ -131,7 +131,7 @@ The script should emit a parity report that feeds into the Downloads workspace ( - [ ] Matrix reflects latest command availability (statuses accurate, task IDs linked). - [ ] Notes include owning backlog items for every 🟩 / 🟡 row. -- [ ] CLI commands marked ✅ have corresponding entries in `/docs/cli/*.md` or module-specific docs. +- [ ] CLI commands marked ✅ have corresponding entries in `/docs/modules/cli/guides/*.md` or module-specific docs. - [ ] CI parity workflow description kept in sync with CONSOLE-DOC-23-502 implementation. - [ ] Downloads workspace links to latest parity report. - [ ] Install / observability guides reference this matrix for pending CLI parity. diff --git a/docs/concelier-connector-research-20251011.md b/docs/concelier-connector-research-20251011.md index 84de135e..15bf2a9a 100644 --- a/docs/concelier-connector-research-20251011.md +++ b/docs/concelier-connector-research-20251011.md @@ -8,7 +8,7 @@ Snapshot of direct network checks performed on 2025-10-11 (UTC) for the national ## CCCS (Canada) - JSON endpoint (`https://www.cyber.gc.ca/api/cccs/threats/v1/get?lang=&content_type=cccs_threat`) returns ~5 100 records per language; `page=` still works for segmented pulls and the earliest `date_created` seen is 2018‑06‑08 (EN) / 2018‑06‑08 (FR). Use an explicit `User-Agent` to avoid 403 responses. -- Follow-up: telemetry, sanitiser coverage, and backfill procedures are documented in `docs/ops/concelier-cccs-operations.md` (2025‑10‑15). Adjust `maxEntriesPerFetch` when performing historical sweeps so cursor state remains responsive. +- Follow-up: telemetry, sanitiser coverage, and backfill procedures are documented in `docs/modules/concelier/operations/connectors/cccs.md` (2025‑10‑15). Adjust `maxEntriesPerFetch` when performing historical sweeps so cursor state remains responsive. ## CERT-Bund (Germany) - `https://wid.cert-bund.de/content/public/securityAdvisory/rss` responds 200 without cookies (≈250-item window, German taxonomy). Detail links load an Angular SPA that fetches JSON behind the bootstrap session. diff --git a/docs/deploy/console.md b/docs/deploy/console.md index c336c97b..b28d156e 100644 --- a/docs/deploy/console.md +++ b/docs/deploy/console.md @@ -1,228 +1,228 @@ -# Deploying the StellaOps Console - -> **Audience:** Deployment Guild, Console Guild, operators rolling out the web console. -> **Scope:** Helm and Docker Compose deployment steps, ingress/TLS configuration, required environment variables, health checks, offline/air-gap operation, and compliance checklist (Sprint 23). - -The StellaOps Console ships as part of the `stellaops` stack Helm chart and Compose bundles maintained under `deploy/`. This guide describes the supported deployment paths, the configuration surface, and operational checks needed to run the console in connected or air-gapped environments. - ---- - -## 1. Prerequisites - -- Kubernetes cluster (v1.28+) with ingress controller (NGINX, Traefik, or equivalent) and Cert-Manager for automated TLS, or Docker host for Compose deployments. -- Container registry access to `registry.stella-ops.org` (or mirrored registry) for all images listed in `deploy/releases/*.yaml`. -- Authority service configured with console client (`aud=ui`, scopes `ui.read`, `ui.admin`). -- DNS entry pointing to the console hostname (for example, `console.acme.internal`). -- Cosign public key for manifest verification (`deploy/releases/manifest.json.sig`). -- Optional: Offline Kit bundle for air-gapped sites (`stella-ops-offline-kit-.tar.gz`). - ---- - -## 2. Helm deployment (recommended) - -### 2.1 Install chart repository - -```bash -helm repo add stellaops https://downloads.stella-ops.org/helm -helm repo update stellaops -``` - -If operating offline, copy the chart archive from the Offline Kit (`deploy/helm/stellaops-.tgz`) and run: - -```bash -helm install stellaops ./stellaops-.tgz --namespace stellaops --create-namespace -``` - -### 2.2 Base installation - -```bash -helm install stellaops stellaops/stellaops \ - --namespace stellaops \ - --create-namespace \ - --values deploy/helm/stellaops/values-prod.yaml -``` - -The chart deploys Authority, Console web/API gateway, Scanner API, Scheduler, and supporting services. The console frontend pod is labelled `app=stellaops-web-ui`. - -### 2.3 Helm values highlights - -Key sections in `deploy/helm/stellaops/values-prod.yaml`: - -| Path | Description | -|------|-------------| -| `console.ingress.host` | Hostname served by the console (`console.example.com`). | -| `console.ingress.tls.secretName` | Kubernetes secret containing TLS certificate (generated by Cert-Manager or uploaded manually). | -| `console.config.apiGateway.baseUrl` | Internal base URL the UI uses to reach the gateway (defaults to `https://stellaops-web`). | -| `console.env.AUTHORITY_ISSUER` | Authority issuer URL (for example, `https://authority.example.com`). | -| `console.env.AUTHORITY_CLIENT_ID` | Authority client ID for the console UI. | -| `console.env.AUTHORITY_SCOPES` | Space-separated scopes required by UI (`ui.read ui.admin`). | -| `console.resources` | CPU/memory requests and limits (default 250m CPU / 512Mi memory). | -| `console.podAnnotations` | Optional annotations for service mesh or monitoring. | - -Use `values-stage.yaml`, `values-dev.yaml`, or `values-airgap.yaml` as templates for other environments. - -### 2.4 TLS and ingress - -Example ingress override: - -```yaml -console: - ingress: - enabled: true - className: nginx - host: console.acme.internal - tls: - enabled: true - secretName: console-tls -``` - -Generate certificates using Cert-Manager or provide an existing secret. For air-gapped deployments, pre-create the secret with the mirrored CA chain. - -### 2.5 Health checks - -Console pods expose: - -| Path | Purpose | Notes | -|------|---------|-------| -| `/health/live` | Liveness probe | Confirms process responsive. | -| `/health/ready` | Readiness probe | Verifies configuration bootstrap and Authority reachability. | -| `/metrics` | Prometheus metrics | Enabled when `console.metrics.enabled=true`. | - -Helm chart sets default probes (`initialDelaySeconds: 10`, `periodSeconds: 15`). Adjust via `console.livenessProbe` and `console.readinessProbe`. - ---- - -## 3. Docker Compose deployment - -Located in `deploy/compose/docker-compose.console.yaml`. Quick start: - -```bash -cd deploy/compose -docker compose -f docker-compose.console.yaml --env-file console.env up -d -``` - -`console.env` should define: - -``` -CONSOLE_PUBLIC_BASE_URL=https://console.acme.internal -AUTHORITY_ISSUER=https://authority.acme.internal -AUTHORITY_CLIENT_ID=console-ui -AUTHORITY_CLIENT_SECRET= -AUTHORITY_SCOPES=ui.read ui.admin -CONSOLE_GATEWAY_BASE_URL=https://api.acme.internal -``` - -The compose bundle includes Traefik as reverse proxy with TLS termination. Update `traefik/dynamic/console.yml` for custom certificates or additional middlewares (CSP headers, rate limits). - ---- - -## 4. Environment variables - -| Variable | Description | Default | -|----------|-------------|---------| -| `CONSOLE_PUBLIC_BASE_URL` | External URL used for redirects, deep links, and telemetry. | None (required). | -| `CONSOLE_GATEWAY_BASE_URL` | URL of the web gateway that proxies API calls (`/console/*`). | Chart service name. | -| `AUTHORITY_ISSUER` | Authority issuer (`https://authority.example.com`). | None (required). | -| `AUTHORITY_CLIENT_ID` | OIDC client configured in Authority. | None (required). | -| `AUTHORITY_SCOPES` | Space-separated scopes assigned to the console client. | `ui.read ui.admin`. | -| `AUTHORITY_DPOP_ENABLED` | Enables DPoP challenge/response (recommended true). | `true`. | -| `CONSOLE_FEATURE_FLAGS` | Comma-separated feature flags (`runs`, `downloads.offline`, etc.). | `runs,downloads,policies`. | -| `CONSOLE_LOG_LEVEL` | Minimum log level (`Information`, `Debug`, etc.). | `Information`. | -| `CONSOLE_METRICS_ENABLED` | Expose `/metrics` endpoint. | `true`. | -| `CONSOLE_SENTRY_DSN` | Optional error reporting DSN. | Blank. | - -When running behind additional proxies, set `ASPNETCORE_FORWARDEDHEADERS_ENABLED=true` to honour `X-Forwarded-*` headers. - ---- - -## 5. Security headers and CSP - -The console serves a strict Content Security Policy (CSP) by default: - -``` -default-src 'self'; -connect-src 'self' https://*.stella-ops.local; -script-src 'self'; -style-src 'self' 'unsafe-inline'; -img-src 'self' data:; -font-src 'self'; -frame-ancestors 'none'; -``` - -Adjust via `console.config.cspOverrides` if additional domains are required. For integrations embedding the console, update OIDC redirect URIs and Authority scopes accordingly. - -TLS recommendations: - -- Use TLS 1.2+ with modern cipher suite policy. -- Enable HSTS (`Strict-Transport-Security: max-age=31536000; includeSubDomains`). -- Provide custom trust bundles via `console.config.trustBundleSecret` when using private CAs. - ---- - -## 6. Logging and metrics - -- Structured logs emitted to stdout with correlation IDs. Configure log shipping via Fluent Bit or similar. -- Metrics available at `/metrics` in Prometheus format. Key metrics include `ui_request_duration_seconds`, `ui_tenant_switch_total`, and `ui_download_manifest_refresh_seconds`. -- Enable OpenTelemetry exporter by setting `OTEL_EXPORTER_OTLP_ENDPOINT` and associated headers in environment variables. - ---- - -## 7. Offline and air-gap deployment - -- Mirror container images using the Downloads workspace or Offline Kit manifest. Example: - -```bash -oras copy registry.stella-ops.org/stellaops/web-ui@sha256: \ - registry.airgap.local/stellaops/web-ui:2025.10.0 -``` - -- Import Offline Kit using `stella ouk import` before starting the console so manifest parity checks succeed. -- Use `values-airgap.yaml` to disable external telemetry endpoints and configure internal certificate chains. -- Run `helm upgrade --install` using the mirrored chart (`stellaops-.tgz`) and set `console.offlineMode=true` to surface offline banners. - ---- - -## 8. Health checks and remediation - -| Check | Command | Expected result | -|-------|---------|-----------------| -| Pod status | `kubectl get pods -n stellaops` | `Running` state with restarts = 0. | -| Liveness | `kubectl exec deploy/stellaops-web-ui -- curl -fsS http://localhost:8080/health/live` | Returns `{"status":"Healthy"}`. | -| Readiness | `kubectl exec deploy/stellaops-web-ui -- curl -fsS http://localhost:8080/health/ready` | Returns `{"status":"Ready"}`. | -| Gateway reachability | `curl -I https://console.example.com/api/console/status` | `200 OK` with CSP headers. | -| Static assets | `curl -I https://console.example.com/static/assets/app.js` | `200 OK` with long cache headers. | - -Troubleshooting steps: - -- **Authority unreachable:** readiness fails with `AUTHORITY_UNREACHABLE`. Check DNS, trust bundles, and Authority service health. -- **Manifest mismatch:** console logs `DOWNLOAD_MANIFEST_SIGNATURE_INVALID`. Verify cosign key and re-sync manifest. -- **Ingress 404:** ensure ingress controller routes host to `stellaops-web-ui` service; check TLS secret name. -- **SSE blocked:** confirm proxy allows HTTP/1.1 and disables buffering on `/console/runs/*`. - ---- - -## 9. References - -- `deploy/helm/stellaops/values-*.yaml` - environment-specific overrides. -- `deploy/compose/docker-compose.console.yaml` - Compose bundle. -- `/docs/ui/downloads.md` - manifest and offline bundle guidance. -- `/docs/security/console-security.md` - CSP and Authority scopes. -- `/docs/24_OFFLINE_KIT.md` - Offline kit packaging and verification. -- `/docs/ops/deployment-runbook.md` (pending) - wider platform deployment steps. - ---- - -## 10. Compliance checklist - -- [ ] Helm and Compose instructions verified against `deploy/` assets. -- [ ] Ingress/TLS guidance aligns with Security Guild recommendations. -- [ ] Environment variables documented with defaults and required values. -- [ ] Health/liveness/readiness endpoints tested and listed. -- [ ] Offline workflow (mirrors, manifest parity) captured. -- [ ] Logging and metrics surface documented metrics. -- [ ] CSP and security header defaults stated alongside override guidance. -- [ ] Troubleshooting section linked to relevant runbooks. - ---- - -*Last updated: 2025-10-27 (Sprint 23).* +# Deploying the StellaOps Console + +> **Audience:** Deployment Guild, Console Guild, operators rolling out the web console. +> **Scope:** Helm and Docker Compose deployment steps, ingress/TLS configuration, required environment variables, health checks, offline/air-gap operation, and compliance checklist (Sprint 23). + +The StellaOps Console ships as part of the `stellaops` stack Helm chart and Compose bundles maintained under `deploy/`. This guide describes the supported deployment paths, the configuration surface, and operational checks needed to run the console in connected or air-gapped environments. + +--- + +## 1. Prerequisites + +- Kubernetes cluster (v1.28+) with ingress controller (NGINX, Traefik, or equivalent) and Cert-Manager for automated TLS, or Docker host for Compose deployments. +- Container registry access to `registry.stella-ops.org` (or mirrored registry) for all images listed in `deploy/releases/*.yaml`. +- Authority service configured with console client (`aud=ui`, scopes `ui.read`, `ui.admin`). +- DNS entry pointing to the console hostname (for example, `console.acme.internal`). +- Cosign public key for manifest verification (`deploy/releases/manifest.json.sig`). +- Optional: Offline Kit bundle for air-gapped sites (`stella-ops-offline-kit-.tar.gz`). + +--- + +## 2. Helm deployment (recommended) + +### 2.1 Install chart repository + +```bash +helm repo add stellaops https://downloads.stella-ops.org/helm +helm repo update stellaops +``` + +If operating offline, copy the chart archive from the Offline Kit (`deploy/helm/stellaops-.tgz`) and run: + +```bash +helm install stellaops ./stellaops-.tgz --namespace stellaops --create-namespace +``` + +### 2.2 Base installation + +```bash +helm install stellaops stellaops/stellaops \ + --namespace stellaops \ + --create-namespace \ + --values deploy/helm/stellaops/values-prod.yaml +``` + +The chart deploys Authority, Console web/API gateway, Scanner API, Scheduler, and supporting services. The console frontend pod is labelled `app=stellaops-web-ui`. + +### 2.3 Helm values highlights + +Key sections in `deploy/helm/stellaops/values-prod.yaml`: + +| Path | Description | +|------|-------------| +| `console.ingress.host` | Hostname served by the console (`console.example.com`). | +| `console.ingress.tls.secretName` | Kubernetes secret containing TLS certificate (generated by Cert-Manager or uploaded manually). | +| `console.config.apiGateway.baseUrl` | Internal base URL the UI uses to reach the gateway (defaults to `https://stellaops-web`). | +| `console.env.AUTHORITY_ISSUER` | Authority issuer URL (for example, `https://authority.example.com`). | +| `console.env.AUTHORITY_CLIENT_ID` | Authority client ID for the console UI. | +| `console.env.AUTHORITY_SCOPES` | Space-separated scopes required by UI (`ui.read ui.admin`). | +| `console.resources` | CPU/memory requests and limits (default 250m CPU / 512Mi memory). | +| `console.podAnnotations` | Optional annotations for service mesh or monitoring. | + +Use `values-stage.yaml`, `values-dev.yaml`, or `values-airgap.yaml` as templates for other environments. + +### 2.4 TLS and ingress + +Example ingress override: + +```yaml +console: + ingress: + enabled: true + className: nginx + host: console.acme.internal + tls: + enabled: true + secretName: console-tls +``` + +Generate certificates using Cert-Manager or provide an existing secret. For air-gapped deployments, pre-create the secret with the mirrored CA chain. + +### 2.5 Health checks + +Console pods expose: + +| Path | Purpose | Notes | +|------|---------|-------| +| `/health/live` | Liveness probe | Confirms process responsive. | +| `/health/ready` | Readiness probe | Verifies configuration bootstrap and Authority reachability. | +| `/metrics` | Prometheus metrics | Enabled when `console.metrics.enabled=true`. | + +Helm chart sets default probes (`initialDelaySeconds: 10`, `periodSeconds: 15`). Adjust via `console.livenessProbe` and `console.readinessProbe`. + +--- + +## 3. Docker Compose deployment + +Located in `deploy/compose/docker-compose.console.yaml`. Quick start: + +```bash +cd deploy/compose +docker compose -f docker-compose.console.yaml --env-file console.env up -d +``` + +`console.env` should define: + +``` +CONSOLE_PUBLIC_BASE_URL=https://console.acme.internal +AUTHORITY_ISSUER=https://authority.acme.internal +AUTHORITY_CLIENT_ID=console-ui +AUTHORITY_CLIENT_SECRET= +AUTHORITY_SCOPES=ui.read ui.admin +CONSOLE_GATEWAY_BASE_URL=https://api.acme.internal +``` + +The compose bundle includes Traefik as reverse proxy with TLS termination. Update `traefik/dynamic/console.yml` for custom certificates or additional middlewares (CSP headers, rate limits). + +--- + +## 4. Environment variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `CONSOLE_PUBLIC_BASE_URL` | External URL used for redirects, deep links, and telemetry. | None (required). | +| `CONSOLE_GATEWAY_BASE_URL` | URL of the web gateway that proxies API calls (`/console/*`). | Chart service name. | +| `AUTHORITY_ISSUER` | Authority issuer (`https://authority.example.com`). | None (required). | +| `AUTHORITY_CLIENT_ID` | OIDC client configured in Authority. | None (required). | +| `AUTHORITY_SCOPES` | Space-separated scopes assigned to the console client. | `ui.read ui.admin`. | +| `AUTHORITY_DPOP_ENABLED` | Enables DPoP challenge/response (recommended true). | `true`. | +| `CONSOLE_FEATURE_FLAGS` | Comma-separated feature flags (`runs`, `downloads.offline`, etc.). | `runs,downloads,policies`. | +| `CONSOLE_LOG_LEVEL` | Minimum log level (`Information`, `Debug`, etc.). | `Information`. | +| `CONSOLE_METRICS_ENABLED` | Expose `/metrics` endpoint. | `true`. | +| `CONSOLE_SENTRY_DSN` | Optional error reporting DSN. | Blank. | + +When running behind additional proxies, set `ASPNETCORE_FORWARDEDHEADERS_ENABLED=true` to honour `X-Forwarded-*` headers. + +--- + +## 5. Security headers and CSP + +The console serves a strict Content Security Policy (CSP) by default: + +``` +default-src 'self'; +connect-src 'self' https://*.stella-ops.local; +script-src 'self'; +style-src 'self' 'unsafe-inline'; +img-src 'self' data:; +font-src 'self'; +frame-ancestors 'none'; +``` + +Adjust via `console.config.cspOverrides` if additional domains are required. For integrations embedding the console, update OIDC redirect URIs and Authority scopes accordingly. + +TLS recommendations: + +- Use TLS 1.2+ with modern cipher suite policy. +- Enable HSTS (`Strict-Transport-Security: max-age=31536000; includeSubDomains`). +- Provide custom trust bundles via `console.config.trustBundleSecret` when using private CAs. + +--- + +## 6. Logging and metrics + +- Structured logs emitted to stdout with correlation IDs. Configure log shipping via Fluent Bit or similar. +- Metrics available at `/metrics` in Prometheus format. Key metrics include `ui_request_duration_seconds`, `ui_tenant_switch_total`, and `ui_download_manifest_refresh_seconds`. +- Enable OpenTelemetry exporter by setting `OTEL_EXPORTER_OTLP_ENDPOINT` and associated headers in environment variables. + +--- + +## 7. Offline and air-gap deployment + +- Mirror container images using the Downloads workspace or Offline Kit manifest. Example: + +```bash +oras copy registry.stella-ops.org/stellaops/web-ui@sha256: \ + registry.airgap.local/stellaops/web-ui:2025.10.0 +``` + +- Import Offline Kit using `stella ouk import` before starting the console so manifest parity checks succeed. +- Use `values-airgap.yaml` to disable external telemetry endpoints and configure internal certificate chains. +- Run `helm upgrade --install` using the mirrored chart (`stellaops-.tgz`) and set `console.offlineMode=true` to surface offline banners. + +--- + +## 8. Health checks and remediation + +| Check | Command | Expected result | +|-------|---------|-----------------| +| Pod status | `kubectl get pods -n stellaops` | `Running` state with restarts = 0. | +| Liveness | `kubectl exec deploy/stellaops-web-ui -- curl -fsS http://localhost:8080/health/live` | Returns `{"status":"Healthy"}`. | +| Readiness | `kubectl exec deploy/stellaops-web-ui -- curl -fsS http://localhost:8080/health/ready` | Returns `{"status":"Ready"}`. | +| Gateway reachability | `curl -I https://console.example.com/api/console/status` | `200 OK` with CSP headers. | +| Static assets | `curl -I https://console.example.com/static/assets/app.js` | `200 OK` with long cache headers. | + +Troubleshooting steps: + +- **Authority unreachable:** readiness fails with `AUTHORITY_UNREACHABLE`. Check DNS, trust bundles, and Authority service health. +- **Manifest mismatch:** console logs `DOWNLOAD_MANIFEST_SIGNATURE_INVALID`. Verify cosign key and re-sync manifest. +- **Ingress 404:** ensure ingress controller routes host to `stellaops-web-ui` service; check TLS secret name. +- **SSE blocked:** confirm proxy allows HTTP/1.1 and disables buffering on `/console/runs/*`. + +--- + +## 9. References + +- `deploy/helm/stellaops/values-*.yaml` - environment-specific overrides. +- `deploy/compose/docker-compose.console.yaml` - Compose bundle. +- `/docs/ui/downloads.md` - manifest and offline bundle guidance. +- `/docs/security/console-security.md` - CSP and Authority scopes. +- `/docs/24_OFFLINE_KIT.md` - Offline kit packaging and verification. +- `/docs/modules/devops/runbooks/deployment-runbook.md` (pending) - wider platform deployment steps. + +--- + +## 10. Compliance checklist + +- [ ] Helm and Compose instructions verified against `deploy/` assets. +- [ ] Ingress/TLS guidance aligns with Security Guild recommendations. +- [ ] Environment variables documented with defaults and required values. +- [ ] Health/liveness/readiness endpoints tested and listed. +- [ ] Offline workflow (mirrors, manifest parity) captured. +- [ ] Logging and metrics surface documented metrics. +- [ ] CSP and security header defaults stated alongside override guidance. +- [ ] Troubleshooting section linked to relevant runbooks. + +--- + +*Last updated: 2025-10-27 (Sprint 23).* diff --git a/docs/deploy/containers.md b/docs/deploy/containers.md index b361b321..4b6a21e2 100644 --- a/docs/deploy/containers.md +++ b/docs/deploy/containers.md @@ -1,160 +1,160 @@ -# Container Deployment Guide — AOC Update - -> **Audience:** DevOps Guild, platform operators deploying StellaOps services. -> **Scope:** Deployment configuration changes required by the Aggregation-Only Contract (AOC), including schema validators, guard environment flags, and verifier identities. - -This guide supplements existing deployment manuals with AOC-specific configuration. It assumes familiarity with the base Compose/Helm manifests described in `ops/deployment/` and `docs/ARCHITECTURE_DEVOPS.md`. - ---- - -## 1 · Schema validator enablement - -### 1.1 MongoDB validators - -- Apply JSON schema validators to `advisory_raw` and `vex_raw` collections before enabling AOC guards. -- Before enabling validators or the idempotency index, run the duplicate audit helper to confirm no conflicting raw advisories remain: - ```bash - mongo concelier ops/devops/scripts/check-advisory-raw-duplicates.js --eval 'var LIMIT=200;' - ``` - Resolve any reported rows prior to rollout. -- Use the migration script provided in `ops/devops/scripts/apply-aoc-validators.js`: - -```bash -kubectl exec -n concelier deploy/concelier-mongo -- \ - mongo concelier ops/devops/scripts/apply-aoc-validators.js - -kubectl exec -n excititor deploy/excititor-mongo -- \ - mongo excititor ops/devops/scripts/apply-aoc-validators.js -``` - -- Validators enforce required fields (`tenant`, `source`, `upstream`, `linkset`) and reject forbidden keys at DB level. -- Rollback plan: validators are applied with `validationLevel: moderate`—downgrade via the same script with `--remove` if required. - -### 1.2 Migration order - -1. Deploy validators in maintenance window. -2. Roll out Concelier/Excititor images with guard middleware enabled (`AOC_GUARD_ENABLED=true`). -3. Run smoke tests (`stella sources ingest --dry-run` fixtures) before resuming production ingestion. - -### 1.3 Supersedes backfill verification - -1. **Duplicate audit:** Confirm `mongo concelier ops/devops/scripts/check-advisory-raw-duplicates.js --eval 'var LIMIT=200;'` reports no conflicts before restarting Concelier with the new migrations. -2. **Post-migration check:** After the service restarts, validate that `db.advisory` is a view pointing to `advisory_backup_20251028`: - ```bash - mongo concelier --quiet --eval 'db.getCollectionInfos({ name: "advisory" })[0]' - ``` - The `type` should be `"view"` and `options.viewOn` should equal `"advisory_backup_20251028"`. -3. **Supersedes chain spot-check:** Inspect a sample set to ensure deterministic chaining: - ```bash - mongo concelier --quiet --eval ' - db.advisory_raw.aggregate([ - { $match: { "upstream.upstream_id": { $exists: true } } }, - { $sort: { "tenant": 1, "source.vendor": 1, "upstream.upstream_id": 1, "upstream.retrieved_at": 1 } }, - { $limit: 5 }, - { $project: { _id: 1, supersedes: 1 } } - ]).forEach(printjson)' - ``` - Each revision should reference the previous `_id` (or `null` for the first revision). Record findings in the change ticket before proceeding to production. - ---- - -## 2 · Container environment flags - -Add the following environment variables to Concelier/Excititor deployments: - -| Variable | Default | Description | -|----------|---------|-------------| -| `AOC_GUARD_ENABLED` | `true` | Enables `AOCWriteGuard` interception. Set `false` only for controlled rollback. | -| `AOC_ALLOW_SUPERSEDES_RETROFIT` | `false` | Allows temporary supersedes backfill during migration. Remove after cutover. | -| `AOC_METRICS_ENABLED` | `true` | Emits `ingestion_write_total`, `aoc_violation_total`, etc. | -| `AOC_TENANT_HEADER` | `X-Stella-Tenant` | Header name expected from Gateway. | -| `AOC_VERIFIER_USER` | `stella-aoc-verify` | Read-only service user used by UI/CLI verification. | - -Compose snippet: - -```yaml -environment: - - AOC_GUARD_ENABLED=true - - AOC_ALLOW_SUPERSEDES_RETROFIT=false - - AOC_METRICS_ENABLED=true - - AOC_TENANT_HEADER=X-Stella-Tenant - - AOC_VERIFIER_USER=stella-aoc-verify -``` - -Ensure `AOC_VERIFIER_USER` exists in Authority with `aoc:verify` scope and no write permissions. - ---- - -## 3 · Verifier identity - -- Create a dedicated client (`stella-aoc-verify`) via Authority bootstrap: - -```yaml -clients: - - clientId: stella-aoc-verify - grantTypes: [client_credentials] - scopes: [aoc:verify, advisory:read, vex:read] - tenants: [default] -``` - -- Store credentials in secret store (`Kubernetes Secret`, `Docker swarm secret`). -- Bind credentials to `stella aoc verify` CI jobs and Console verification service. -- Rotate quarterly; document in `ops/authority-key-rotation.md`. - ---- - -## 4 · Deployment steps - -1. **Pre-checks:** Confirm database backups, alerting in maintenance mode, and staging environment validated. -2. **Apply validators:** Run scripts per § 1.1. -3. **Update manifests:** Inject environment variables (§ 2) and mount guard configuration configmaps. -4. **Redeploy services:** Rolling restart Concelier/Excititor pods. Monitor `ingestion_write_total` for steady throughput. -5. **Seed verifier:** Deploy read-only verifier user and store credentials. -6. **Run verification:** Execute `stella aoc verify --since 24h` and ensure exit code `0`. -7. **Update dashboards:** Point Grafana panels to new metrics (`aoc_violation_total`). -8. **Record handoff:** Capture console screenshots and verification logs for release notes. - ---- - -## 5 · Offline Kit updates - -- Ship validator scripts with Offline Kit (`offline-kit/scripts/apply-aoc-validators.js`). -- Include pre-generated verification reports for air-gapped deployments. -- Document offline CLI workflow in bundle README referencing `docs/cli/cli-reference.md`. -- Ensure `stella-aoc-verify` credentials are scoped to offline tenant and rotated during bundle refresh. - ---- - -## 6 · Rollback plan - -1. Disable guard via `AOC_GUARD_ENABLED=false` on Concelier/Excititor and rollout. -2. Remove validators with the migration script (`--remove`). -3. Pause verification jobs to prevent noise. -4. Investigate and remediate upstream issues before re-enabling guards. - ---- - -## 7 · References - -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) -- [Authority scopes & tenancy](../security/authority-scopes.md) -- [Observability guide](../observability/observability.md) -- [CLI AOC commands](../cli/cli-reference.md) -- [Concelier architecture](../ARCHITECTURE_CONCELIER.md) -- [Excititor architecture](../ARCHITECTURE_EXCITITOR.md) - ---- - -## 8 · Compliance checklist - -- [ ] Validators documented and scripts referenced for online/offline deployments. -- [ ] Environment variables cover guard enablement, metrics, and tenant header. -- [ ] Read-only verifier user installation steps included. -- [ ] Offline kit instructions align with validator/verification workflow. -- [ ] Rollback procedure captured. -- [ ] Cross-links to AOC docs, Authority scopes, and observability guides present. -- [ ] DevOps Guild sign-off tracked (owner: @devops-guild, due 2025-10-29). - ---- - -*Last updated: 2025-10-26 (Sprint 19).* +# Container Deployment Guide — AOC Update + +> **Audience:** DevOps Guild, platform operators deploying StellaOps services. +> **Scope:** Deployment configuration changes required by the Aggregation-Only Contract (AOC), including schema validators, guard environment flags, and verifier identities. + +This guide supplements existing deployment manuals with AOC-specific configuration. It assumes familiarity with the base Compose/Helm manifests described in `ops/deployment/` and `docs/modules/devops/architecture.md`. + +--- + +## 1 · Schema validator enablement + +### 1.1 MongoDB validators + +- Apply JSON schema validators to `advisory_raw` and `vex_raw` collections before enabling AOC guards. +- Before enabling validators or the idempotency index, run the duplicate audit helper to confirm no conflicting raw advisories remain: + ```bash + mongo concelier ops/devops/scripts/check-advisory-raw-duplicates.js --eval 'var LIMIT=200;' + ``` + Resolve any reported rows prior to rollout. +- Use the migration script provided in `ops/devops/scripts/apply-aoc-validators.js`: + +```bash +kubectl exec -n concelier deploy/concelier-mongo -- \ + mongo concelier ops/devops/scripts/apply-aoc-validators.js + +kubectl exec -n excititor deploy/excititor-mongo -- \ + mongo excititor ops/devops/scripts/apply-aoc-validators.js +``` + +- Validators enforce required fields (`tenant`, `source`, `upstream`, `linkset`) and reject forbidden keys at DB level. +- Rollback plan: validators are applied with `validationLevel: moderate`—downgrade via the same script with `--remove` if required. + +### 1.2 Migration order + +1. Deploy validators in maintenance window. +2. Roll out Concelier/Excititor images with guard middleware enabled (`AOC_GUARD_ENABLED=true`). +3. Run smoke tests (`stella sources ingest --dry-run` fixtures) before resuming production ingestion. + +### 1.3 Supersedes backfill verification + +1. **Duplicate audit:** Confirm `mongo concelier ops/devops/scripts/check-advisory-raw-duplicates.js --eval 'var LIMIT=200;'` reports no conflicts before restarting Concelier with the new migrations. +2. **Post-migration check:** After the service restarts, validate that `db.advisory` is a view pointing to `advisory_backup_20251028`: + ```bash + mongo concelier --quiet --eval 'db.getCollectionInfos({ name: "advisory" })[0]' + ``` + The `type` should be `"view"` and `options.viewOn` should equal `"advisory_backup_20251028"`. +3. **Supersedes chain spot-check:** Inspect a sample set to ensure deterministic chaining: + ```bash + mongo concelier --quiet --eval ' + db.advisory_raw.aggregate([ + { $match: { "upstream.upstream_id": { $exists: true } } }, + { $sort: { "tenant": 1, "source.vendor": 1, "upstream.upstream_id": 1, "upstream.retrieved_at": 1 } }, + { $limit: 5 }, + { $project: { _id: 1, supersedes: 1 } } + ]).forEach(printjson)' + ``` + Each revision should reference the previous `_id` (or `null` for the first revision). Record findings in the change ticket before proceeding to production. + +--- + +## 2 · Container environment flags + +Add the following environment variables to Concelier/Excititor deployments: + +| Variable | Default | Description | +|----------|---------|-------------| +| `AOC_GUARD_ENABLED` | `true` | Enables `AOCWriteGuard` interception. Set `false` only for controlled rollback. | +| `AOC_ALLOW_SUPERSEDES_RETROFIT` | `false` | Allows temporary supersedes backfill during migration. Remove after cutover. | +| `AOC_METRICS_ENABLED` | `true` | Emits `ingestion_write_total`, `aoc_violation_total`, etc. | +| `AOC_TENANT_HEADER` | `X-Stella-Tenant` | Header name expected from Gateway. | +| `AOC_VERIFIER_USER` | `stella-aoc-verify` | Read-only service user used by UI/CLI verification. | + +Compose snippet: + +```yaml +environment: + - AOC_GUARD_ENABLED=true + - AOC_ALLOW_SUPERSEDES_RETROFIT=false + - AOC_METRICS_ENABLED=true + - AOC_TENANT_HEADER=X-Stella-Tenant + - AOC_VERIFIER_USER=stella-aoc-verify +``` + +Ensure `AOC_VERIFIER_USER` exists in Authority with `aoc:verify` scope and no write permissions. + +--- + +## 3 · Verifier identity + +- Create a dedicated client (`stella-aoc-verify`) via Authority bootstrap: + +```yaml +clients: + - clientId: stella-aoc-verify + grantTypes: [client_credentials] + scopes: [aoc:verify, advisory:read, vex:read] + tenants: [default] +``` + +- Store credentials in secret store (`Kubernetes Secret`, `Docker swarm secret`). +- Bind credentials to `stella aoc verify` CI jobs and Console verification service. +- Rotate quarterly; document in `ops/authority-key-rotation.md`. + +--- + +## 4 · Deployment steps + +1. **Pre-checks:** Confirm database backups, alerting in maintenance mode, and staging environment validated. +2. **Apply validators:** Run scripts per § 1.1. +3. **Update manifests:** Inject environment variables (§ 2) and mount guard configuration configmaps. +4. **Redeploy services:** Rolling restart Concelier/Excititor pods. Monitor `ingestion_write_total` for steady throughput. +5. **Seed verifier:** Deploy read-only verifier user and store credentials. +6. **Run verification:** Execute `stella aoc verify --since 24h` and ensure exit code `0`. +7. **Update dashboards:** Point Grafana panels to new metrics (`aoc_violation_total`). +8. **Record handoff:** Capture console screenshots and verification logs for release notes. + +--- + +## 5 · Offline Kit updates + +- Ship validator scripts with Offline Kit (`offline-kit/scripts/apply-aoc-validators.js`). +- Include pre-generated verification reports for air-gapped deployments. +- Document offline CLI workflow in bundle README referencing `docs/modules/cli/guides/cli-reference.md`. +- Ensure `stella-aoc-verify` credentials are scoped to offline tenant and rotated during bundle refresh. + +--- + +## 6 · Rollback plan + +1. Disable guard via `AOC_GUARD_ENABLED=false` on Concelier/Excititor and rollout. +2. Remove validators with the migration script (`--remove`). +3. Pause verification jobs to prevent noise. +4. Investigate and remediate upstream issues before re-enabling guards. + +--- + +## 7 · References + +- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) +- [Authority scopes & tenancy](../security/authority-scopes.md) +- [Observability guide](../observability/observability.md) +- [CLI AOC commands](../modules/cli/guides/cli-reference.md) +- [Concelier architecture](../modules/concelier/architecture.md) +- [Excititor architecture](../modules/excititor/architecture.md) + +--- + +## 8 · Compliance checklist + +- [ ] Validators documented and scripts referenced for online/offline deployments. +- [ ] Environment variables cover guard enablement, metrics, and tenant header. +- [ ] Read-only verifier user installation steps included. +- [ ] Offline kit instructions align with validator/verification workflow. +- [ ] Rollback procedure captured. +- [ ] Cross-links to AOC docs, Authority scopes, and observability guides present. +- [ ] DevOps Guild sign-off tracked (owner: @devops-guild, due 2025-10-29). + +--- + +*Last updated: 2025-10-26 (Sprint 19).* diff --git a/docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md b/docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md index c0fc6c5a..fcb67ef2 100644 --- a/docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md +++ b/docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md @@ -2,7 +2,7 @@ > **Audience:** teams implementing new Excititor provider plug‑ins (CSAF feeds, > OpenVEX attestations, etc.) -> **Prerequisites:** read `docs/ARCHITECTURE_EXCITITOR.md` and the module +> **Prerequisites:** read `docs/modules/excititor/architecture.md` and the module > `AGENTS.md` in `src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/`. The Excititor connector SDK gives you: diff --git a/docs/dev/30_VEXER_CONNECTOR_GUIDE.md b/docs/dev/30_VEXER_CONNECTOR_GUIDE.md index 7eba6a8c..328865b0 100644 --- a/docs/dev/30_VEXER_CONNECTOR_GUIDE.md +++ b/docs/dev/30_VEXER_CONNECTOR_GUIDE.md @@ -2,7 +2,7 @@ > **Audience:** teams implementing new Vexer provider plug‑ins (CSAF feeds, > OpenVEX attestations, etc.) -> **Prerequisites:** read `docs/ARCHITECTURE_VEXER.md` and the module +> **Prerequisites:** read `docs/modules/vexer/architecture.md` and the module > `AGENTS.md` in `src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/`. The Vexer connector SDK gives you: diff --git a/docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md b/docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md index 168304c0..ccd83b7f 100644 --- a/docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md +++ b/docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md @@ -116,7 +116,7 @@ Capability flags let the host reason about what your plug-in supports: - Support environment overrides using `STELLAOPS_AUTHORITY_PLUGINS__DESCRIPTORS____...`. - Never store raw secrets in git: allow operators to supply them via `.local.yaml`, environment variables, or injected secret files. Document which keys are mandatory. - Validate configuration as soon as the registrar runs; use explicit error messages to guide operators. The Standard plug-in now enforces complete bootstrap credentials (username + password) and positive lockout windows via `StandardPluginOptions.Validate`. -- Cross-reference bootstrap workflows with `docs/ops/authority_bootstrap.md` (to be published alongside CORE6) so operators can reuse the same payload formats for manual provisioning. +- Cross-reference bootstrap workflows with `docs/modules/authority/operations/bootstrap.md` (to be published alongside CORE6) so operators can reuse the same payload formats for manual provisioning. - `passwordHashing` inherits defaults from `authority.security.passwordHashing`. Override only when hardware constraints differ per plug-in: ```yaml passwordHashing: diff --git a/docs/dev/BUILDX_PLUGIN_QUICKSTART.md b/docs/dev/BUILDX_PLUGIN_QUICKSTART.md index 61a7fd29..4ede203b 100644 --- a/docs/dev/BUILDX_PLUGIN_QUICKSTART.md +++ b/docs/dev/BUILDX_PLUGIN_QUICKSTART.md @@ -116,4 +116,4 @@ Add the workflow to your repository (or call it via `workflow_call`) and adjust --- -For deeper integration guidance (custom SBOM builders, exporting DSSE bundles), track ADRs in `docs/ARCHITECTURE_SCANNER.md` §7 and follow upcoming Attestor API releases. +For deeper integration guidance (custom SBOM builders, exporting DSSE bundles), track ADRs in `docs/modules/scanner/architecture.md` §7 and follow upcoming Attestor API releases. diff --git a/docs/dev/authority-dpop-mtls-plan.md b/docs/dev/authority-dpop-mtls-plan.md index dd5b7f83..6f211db9 100644 --- a/docs/dev/authority-dpop-mtls-plan.md +++ b/docs/dev/authority-dpop-mtls-plan.md @@ -134,13 +134,13 @@ 2. Introduce configuration classes and bind from YAML/environment. 3. Implement nonce store (Redis + in-memory), handler integration, and OpenIddict transaction plumbing. 4. Stamp `cnf.jkt`, audit events, and metrics; update Mongo documents and migrations. -5. Extend docs: `docs/ARCHITECTURE_AUTHORITY.md`, `docs/security/audit-events.md`, `docs/security/rate-limits.md`, CLI/UI references. +5. Extend docs: `docs/modules/authority/architecture.md`, `docs/security/audit-events.md`, `docs/security/rate-limits.md`, CLI/UI references. **mTLS work-stream** 1. Extend client document/schema and provisioning stores with certificate bindings + sender constraint flag. 2. Configure Kestrel/middleware for optional client certificates and validation service. 3. Update token issuance/introspection to honour certificate bindings and emit `cnf.x5t#S256`. 4. Add auditing/metrics and integration tests (happy path + failure). -5. Refresh operator documentation (`docs/ops/authority-backup-restore.md`, `docs/ops/authority-monitoring.md`, sample `authority.yaml`) to cover certificate lifecycle. +5. Refresh operator documentation (`docs/modules/authority/operations/backup-restore.md`, `docs/modules/authority/operations/monitoring.md`, sample `authority.yaml`) to cover certificate lifecycle. Both streams should conclude with `dotnet test src/Authority/StellaOps.Authority/StellaOps.Authority.sln` and documentation cross-links so dependent guilds can unblock UI/Signer work. diff --git a/docs/dev/fixtures.md b/docs/dev/fixtures.md index 4967ce88..eccfdc8b 100644 --- a/docs/dev/fixtures.md +++ b/docs/dev/fixtures.md @@ -11,7 +11,7 @@ fixture sets, where they live, and how to regenerate them safely. - **Purpose:** Exercised by `OsvGhsaParityRegressionTests` to ensure OSV + GHSA outputs stay aligned on aliases, ranges, references, and credits. - **Regeneration:** Either run the test harness with online regeneration (`UPDATE_PARITY_FIXTURES=1 dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csproj`) - or execute the fixture updater (`dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj`). Both paths + or execute the fixture updater (`dotnet run --project src/Tools/FixtureUpdater/FixtureUpdater.csproj`). Both paths normalise timestamps and canonical ordering. - **SemVer provenance:** The regenerated fixtures should show `normalizedVersions[].notes` in the `osv:{ecosystem}:{advisoryId}:{identifier}` shape emitted by `SemVerRangeRuleBuilder`. Confirm the @@ -22,7 +22,7 @@ fixture sets, where they live, and how to regenerate them safely. - **Location:** `src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa.Tests/Fixtures/credit-parity.{ghsa,osv,nvd}.json` - **Purpose:** Exercised by `GhsaCreditParityRegressionTests` to guarantee GHSA/NVD/OSV acknowledgements remain in lockstep. -- **Regeneration:** `dotnet run --project tools/FixtureUpdater/FixtureUpdater.csproj` rewrites all three canonical snapshots. +- **Regeneration:** `dotnet run --project src/Tools/FixtureUpdater/FixtureUpdater.csproj` rewrites all three canonical snapshots. - **Verification:** `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa.Tests/StellaOps.Concelier.Connector.Ghsa.Tests.csproj`. > Always commit fixture changes together with the code that motivated them and reference the regression test that guards the behaviour. diff --git a/docs/dev/merge_semver_playbook.md b/docs/dev/merge_semver_playbook.md index 81c93f2d..63074f06 100644 --- a/docs/dev/merge_semver_playbook.md +++ b/docs/dev/merge_semver_playbook.md @@ -82,10 +82,10 @@ Coordinate with the Storage team when enabling these indexes so deployment windo ## 6. Dual-write rollout -Follow the operational checklist in `docs/ops/migrations/SEMVER_STYLE.md`. The summary: +Follow the operational checklist in `docs/modules/devops/migrations/semver-style.md`. The summary: 1. **Dual write (now)** – emit both legacy `versionRanges` and the new `normalizedVersions`. -2. **Backfill** – follow the storage migration in `docs/ops/migrations/SEMVER_STYLE.md` to rewrite historical advisories before switching consumers. +2. **Backfill** – follow the storage migration in `docs/modules/devops/migrations/semver-style.md` to rewrite historical advisories before switching consumers. 3. **Verify** – run the aggregation above (with `explain("executionStats")`) to ensure the new indexes are used. 4. **Cutover** – after consumers switch to normalized rules, mark the old `rangeExpression` as deprecated. diff --git a/docs/events/orchestrator-scanner-events.md b/docs/events/orchestrator-scanner-events.md index 5f246aef..992fffb9 100644 --- a/docs/events/orchestrator-scanner-events.md +++ b/docs/events/orchestrator-scanner-events.md @@ -1,121 +1,121 @@ -# Scanner Orchestrator Events (ORCH-SVC-38-101) - -Last updated: 2025-10-26 - -The Notifications Studio initiative (NOTIFY-SVC-38-001) and orchestrator backlog (ORCH-SVC-38-101) standardise how platform services emit lifecycle events. This document describes the Scanner WebService contract for the new **orchestrator envelopes** (`scanner.event.*`) and how they supersede the legacy Redis-backed `scanner.report.ready` / `scanner.scan.completed` events. - -## 1. Envelope overview - -Orchestrator events share a deterministic JSON envelope: - -| Field | Type | Notes | -|-------|------|-------| -| `eventId` | `uuid` | Globally unique identifier generated per occurrence. | -| `kind` | `string` | Event identifier; Scanner emits `scanner.event.report.ready` and `scanner.event.scan.completed`. | -| `version` | `integer` | Schema version. Initial release uses `1`. | -| `tenant` | `string` | Tenant that owns the scan/report. Mirrors Authority claims. | -| `occurredAt` | `date-time` | UTC instant when the underlying state transition happened (e.g., report persisted). | -| `recordedAt` | `date-time` | UTC instant when the event was durably written. Optional but recommended. | -| `source` | `string` | Producer identifier (`scanner.webservice`). | -| `idempotencyKey` | `string` | Deterministic key for duplicate suppression (see §4). | -| `correlationId` | `string` | Maps back to the API request or scan identifier. | -| `traceId` / `spanId` | `string` | W3C trace context propagated into downstream telemetry. | -| `scope` | `object` | Describes the affected artefact. Requires `repo` and `digest`; optional `namespace`, `component`, `image`. | -| `attributes` | `object` | Flat string map for frequently queried metadata (e.g., policy revision). | -| `payload` | `object` | Event-specific body (see §2). | - -Canonical schemas live under `docs/events/scanner.event.*@1.json`. Samples that round-trip through `NotifyCanonicalJsonSerializer` are stored in `docs/events/samples/`. - -## 2. Event kinds and payloads - -### 2.1 `scanner.event.report.ready` - -Emitted once a signed report is persisted and attested. Payload highlights: - -- `reportId` / `scanId` — identifiers for the persisted report and originating scan. Until Scan IDs are surfaced by the API, `scanId` mirrors `reportId` so downstream correlators can stabilise on a single key. -- **Attributes:** `reportId`, `policyRevisionId`, `policyDigest`, `verdict` — pre-sorted for deterministic routing. -- **Links:** - - `ui` → `/ui/reports/{reportId}` on the current host. - - `report` → `{apiBasePath}/{reportsSegment}/{reportId}` (defaults to `/api/v1/reports/{reportId}`). - - `policy` → `{apiBasePath}/{policySegment}/revisions/{revisionId}` when a revision is present. - - `attestation` → `/ui/attestations/{reportId}` when a DSSE envelope is included. -- `imageDigest` — OCI image digest associated with the analysis. -- `generatedAt` — report generation timestamp (ISO-8601 UTC). -- `verdict` — `pass`, `warn`, or `fail` after policy evaluation. -- `summary` — blocked/warned/ignored/quieted counters (all non-negative integers). -- `delta` — newly critical/high counts and optional `kev` array. -- `quietedFindingCount` — mirrors `summary.quieted`. -- `policy` — revision metadata (`digest`, `revisionId`) surfaced for routing. -- `links` — UI/report/policy URLs suitable for operators. -- `dsse` — embedded DSSE envelope (payload, type, signature list). -- `report` — canonical report document; identical to the DSSE payload. - -Schema: `docs/events/scanner.event.report.ready@1.json` -Sample: `docs/events/samples/scanner.event.report.ready@1.sample.json` - -### 2.2 `scanner.event.scan.completed` - -Emitted after scan execution finishes (success or policy failure). Payload highlights: - -- `reportId` / `scanId` / `imageDigest` — identifiers mirroring the report-ready event. As with the report-ready payload, `scanId` currently mirrors `reportId` as a temporary shim. -- **Attributes:** `reportId`, `policyRevisionId`, `policyDigest`, `verdict`. -- **Links:** same as above (`ui`, `report`, `policy`) with `attestation` populated when DSSE metadata exists. -- `verdict`, `summary`, `delta`, `policy` — same semantics as above. -- `findings` — array of surfaced findings with `id`, `severity`, optional `cve`, `purl`, and `reachability`. -- `links`, `dsse`, `report` — same structure as §2.1 (allows Notifier to reuse signatures). - -Schema: `docs/events/scanner.event.scan.completed@1.json` -Sample: `docs/events/samples/scanner.event.scan.completed@1.sample.json` - -### 2.3 Relationship to legacy events - -| Legacy Redis event | Replacement orchestrator event | Notes | -|--------------------|-------------------------------|-------| -| `scanner.report.ready` | `scanner.event.report.ready` | Adds versioning, idempotency, trace context. Payload is a superset of the legacy fields. | -| `scanner.scan.completed` | `scanner.event.scan.completed` | Same data plus explicit scan identifiers and orchestrator metadata. | - -Legacy schemas remain for backwards-compatibility during migration, but new integrations **must** target the orchestrator variants. - -## 3. Deterministic serialization - -- Producers must serialise events using `NotifyCanonicalJsonSerializer` to guarantee consistent key ordering and whitespace. -- Timestamps (`occurredAt`, `recordedAt`, `payload.generatedAt`) use `DateTimeOffset.UtcDateTime.ToString("O")`. -- Payload arrays (`delta.kev`, `findings`) should be pre-sorted (e.g., alphabetical CVE order) so hash-based consumers remain stable. -- Optional fields are omitted rather than emitted as `null`. - -## 4. Idempotency and correlation - -Idempotency keys dedupe repeated publishes and align with the orchestrator’s outbox pattern: - -| Event kind | Idempotency key template | -|------------|-------------------------| -| `scanner.event.report.ready` | `scanner.event.report.ready::` | -| `scanner.event.scan.completed` | `scanner.event.scan.completed::` | - -Keys are ASCII lowercase; components should be trimmed and validated before concatenation. Retries must reuse the same key. - -`correlationId` should match the scan identifier that appears in REST responses (`scanId`). Re-using the same value across the pair of events allows Notifier and orchestrator analytics to stitch lifecycle data together. - -## 5. Versioning and evolution - -- Increment the `version` field and the `@` suffix for **breaking** changes (field removals, type changes, semantic shifts). -- Additive optional fields may remain within version 1; update the JSON schema and samples accordingly. -- When introducing `@2`, keep the `@1` schema/docs in place until orchestrator subscribers confirm migration. - -## 6. Consumer checklist - -1. Validate incoming payloads against the schema for the targeted version. -2. Use `idempotencyKey` for dedupe, not `eventId`. -3. Map `traceId`/`spanId` into telemetry spans to preserve causality. -4. Prefer `payload.report` → `policy.revisionId` when populating templates; the top-level `attributes` are convenience duplicates for quick routing. -5. Reserve the legacy Redis events for transitional compatibility only; downstream systems should subscribe to the orchestrator bus exposed by ORCH-SVC-38-101. - -## 7. Implementation status and next actions - -- **Scanner WebService** — `SCANNER-EVENTS-16-301` (blocked) and `SCANNER-EVENTS-16-302` (doing) track the production of these envelopes. The remaining blocker is the .NET 10 preview OpenAPI/Auth dependency drift that currently breaks `dotnet test`. Once Gateway and Notifier owners land the replacement packages, rerun the full test suite and capture fresh fixtures under `docs/events/samples/`. -- **Gateway/Notifier consumers** — subscribe to the orchestrator stream documented in ORCH-SVC-38-101. When the Scanner tasks unblock, regenerate notifier contract tests against the sample events included here. -- **Docs cadence** — update this file and the matching JSON schemas whenever payload fields change. Use the rehearsal checklist in `docs/ops/launch-cutover.md` to confirm downstream validation before the production cutover. Record gaps or newly required fields in `docs/ops/launch-readiness.md` so they land in the launch checklist. - ---- - -**Imposed rule reminder:** work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Scanner Orchestrator Events (ORCH-SVC-38-101) + +Last updated: 2025-10-26 + +The Notifications Studio initiative (NOTIFY-SVC-38-001) and orchestrator backlog (ORCH-SVC-38-101) standardise how platform services emit lifecycle events. This document describes the Scanner WebService contract for the new **orchestrator envelopes** (`scanner.event.*`) and how they supersede the legacy Redis-backed `scanner.report.ready` / `scanner.scan.completed` events. + +## 1. Envelope overview + +Orchestrator events share a deterministic JSON envelope: + +| Field | Type | Notes | +|-------|------|-------| +| `eventId` | `uuid` | Globally unique identifier generated per occurrence. | +| `kind` | `string` | Event identifier; Scanner emits `scanner.event.report.ready` and `scanner.event.scan.completed`. | +| `version` | `integer` | Schema version. Initial release uses `1`. | +| `tenant` | `string` | Tenant that owns the scan/report. Mirrors Authority claims. | +| `occurredAt` | `date-time` | UTC instant when the underlying state transition happened (e.g., report persisted). | +| `recordedAt` | `date-time` | UTC instant when the event was durably written. Optional but recommended. | +| `source` | `string` | Producer identifier (`scanner.webservice`). | +| `idempotencyKey` | `string` | Deterministic key for duplicate suppression (see §4). | +| `correlationId` | `string` | Maps back to the API request or scan identifier. | +| `traceId` / `spanId` | `string` | W3C trace context propagated into downstream telemetry. | +| `scope` | `object` | Describes the affected artefact. Requires `repo` and `digest`; optional `namespace`, `component`, `image`. | +| `attributes` | `object` | Flat string map for frequently queried metadata (e.g., policy revision). | +| `payload` | `object` | Event-specific body (see §2). | + +Canonical schemas live under `docs/events/scanner.event.*@1.json`. Samples that round-trip through `NotifyCanonicalJsonSerializer` are stored in `docs/events/samples/`. + +## 2. Event kinds and payloads + +### 2.1 `scanner.event.report.ready` + +Emitted once a signed report is persisted and attested. Payload highlights: + +- `reportId` / `scanId` — identifiers for the persisted report and originating scan. Until Scan IDs are surfaced by the API, `scanId` mirrors `reportId` so downstream correlators can stabilise on a single key. +- **Attributes:** `reportId`, `policyRevisionId`, `policyDigest`, `verdict` — pre-sorted for deterministic routing. +- **Links:** + - `ui` → `/ui/reports/{reportId}` on the current host. + - `report` → `{apiBasePath}/{reportsSegment}/{reportId}` (defaults to `/api/v1/reports/{reportId}`). + - `policy` → `{apiBasePath}/{policySegment}/revisions/{revisionId}` when a revision is present. + - `attestation` → `/ui/attestations/{reportId}` when a DSSE envelope is included. +- `imageDigest` — OCI image digest associated with the analysis. +- `generatedAt` — report generation timestamp (ISO-8601 UTC). +- `verdict` — `pass`, `warn`, or `fail` after policy evaluation. +- `summary` — blocked/warned/ignored/quieted counters (all non-negative integers). +- `delta` — newly critical/high counts and optional `kev` array. +- `quietedFindingCount` — mirrors `summary.quieted`. +- `policy` — revision metadata (`digest`, `revisionId`) surfaced for routing. +- `links` — UI/report/policy URLs suitable for operators. +- `dsse` — embedded DSSE envelope (payload, type, signature list). +- `report` — canonical report document; identical to the DSSE payload. + +Schema: `docs/events/scanner.event.report.ready@1.json` +Sample: `docs/events/samples/scanner.event.report.ready@1.sample.json` + +### 2.2 `scanner.event.scan.completed` + +Emitted after scan execution finishes (success or policy failure). Payload highlights: + +- `reportId` / `scanId` / `imageDigest` — identifiers mirroring the report-ready event. As with the report-ready payload, `scanId` currently mirrors `reportId` as a temporary shim. +- **Attributes:** `reportId`, `policyRevisionId`, `policyDigest`, `verdict`. +- **Links:** same as above (`ui`, `report`, `policy`) with `attestation` populated when DSSE metadata exists. +- `verdict`, `summary`, `delta`, `policy` — same semantics as above. +- `findings` — array of surfaced findings with `id`, `severity`, optional `cve`, `purl`, and `reachability`. +- `links`, `dsse`, `report` — same structure as §2.1 (allows Notifier to reuse signatures). + +Schema: `docs/events/scanner.event.scan.completed@1.json` +Sample: `docs/events/samples/scanner.event.scan.completed@1.sample.json` + +### 2.3 Relationship to legacy events + +| Legacy Redis event | Replacement orchestrator event | Notes | +|--------------------|-------------------------------|-------| +| `scanner.report.ready` | `scanner.event.report.ready` | Adds versioning, idempotency, trace context. Payload is a superset of the legacy fields. | +| `scanner.scan.completed` | `scanner.event.scan.completed` | Same data plus explicit scan identifiers and orchestrator metadata. | + +Legacy schemas remain for backwards-compatibility during migration, but new integrations **must** target the orchestrator variants. + +## 3. Deterministic serialization + +- Producers must serialise events using `NotifyCanonicalJsonSerializer` to guarantee consistent key ordering and whitespace. +- Timestamps (`occurredAt`, `recordedAt`, `payload.generatedAt`) use `DateTimeOffset.UtcDateTime.ToString("O")`. +- Payload arrays (`delta.kev`, `findings`) should be pre-sorted (e.g., alphabetical CVE order) so hash-based consumers remain stable. +- Optional fields are omitted rather than emitted as `null`. + +## 4. Idempotency and correlation + +Idempotency keys dedupe repeated publishes and align with the orchestrator’s outbox pattern: + +| Event kind | Idempotency key template | +|------------|-------------------------| +| `scanner.event.report.ready` | `scanner.event.report.ready::` | +| `scanner.event.scan.completed` | `scanner.event.scan.completed::` | + +Keys are ASCII lowercase; components should be trimmed and validated before concatenation. Retries must reuse the same key. + +`correlationId` should match the scan identifier that appears in REST responses (`scanId`). Re-using the same value across the pair of events allows Notifier and orchestrator analytics to stitch lifecycle data together. + +## 5. Versioning and evolution + +- Increment the `version` field and the `@` suffix for **breaking** changes (field removals, type changes, semantic shifts). +- Additive optional fields may remain within version 1; update the JSON schema and samples accordingly. +- When introducing `@2`, keep the `@1` schema/docs in place until orchestrator subscribers confirm migration. + +## 6. Consumer checklist + +1. Validate incoming payloads against the schema for the targeted version. +2. Use `idempotencyKey` for dedupe, not `eventId`. +3. Map `traceId`/`spanId` into telemetry spans to preserve causality. +4. Prefer `payload.report` → `policy.revisionId` when populating templates; the top-level `attributes` are convenience duplicates for quick routing. +5. Reserve the legacy Redis events for transitional compatibility only; downstream systems should subscribe to the orchestrator bus exposed by ORCH-SVC-38-101. + +## 7. Implementation status and next actions + +- **Scanner WebService** — `SCANNER-EVENTS-16-301` (blocked) and `SCANNER-EVENTS-16-302` (doing) track the production of these envelopes. The remaining blocker is the .NET 10 preview OpenAPI/Auth dependency drift that currently breaks `dotnet test`. Once Gateway and Notifier owners land the replacement packages, rerun the full test suite and capture fresh fixtures under `docs/events/samples/`. +- **Gateway/Notifier consumers** — subscribe to the orchestrator stream documented in ORCH-SVC-38-101. When the Scanner tasks unblock, regenerate notifier contract tests against the sample events included here. +- **Docs cadence** — update this file and the matching JSON schemas whenever payload fields change. Use the rehearsal checklist in `docs/modules/devops/runbooks/launch-cutover.md` to confirm downstream validation before the production cutover. Record gaps or newly required fields in `docs/modules/devops/runbooks/launch-readiness.md` so they land in the launch checklist. + +--- + +**Imposed rule reminder:** work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/implplan/AGENTS.md b/docs/implplan/AGENTS.md deleted file mode 100644 index 393b6feb..00000000 --- a/docs/implplan/AGENTS.md +++ /dev/null @@ -1,112 +0,0 @@ -# 1) What is StellaOps? - -**StellaOps** an open, sovereign, modular container-security toolkit built for high-speed, offline operation, released under AGPL-3.0-or-later. - -It follows an SBOM-first model—analyzing each container layer or ingesting existing CycloneDX/SPDX SBOMs, then enriching them with vulnerability, licence, secret-leak, and misconfiguration data to produce cryptographically signed reports. - -Vulnerability detection maps OS and language dependencies to sources such as NVD, GHSA, OSV, ENISA. -Secrets sweep flags exposed credentials or keys in files or environment variables. -Licence audit identifies potential conflicts, especially copyleft obligations. -Misconfiguration checks detect unsafe Dockerfile patterns (root user, latest tags, permissive modes). -Provenance features include in-toto/SLSA attestations signed with cosign for supply-chain trust. - -| Guiding principle | What it means for Concelier | -|-------------------|---------------------------| -| **SBOM-first ingest** | Prefer signed SBOMs or reproducible layer diffs before falling back to raw scraping; connectors treat source docs as provenance, never as mutable truth. | -| **Deterministic outputs** | Same inputs yield identical canonical advisories and exported JSON/Trivy DB artefacts; merge hashes and export manifests are reproducible across machines. | -| **Restart-time plug-ins only** | Connector/exporter plug-ins load at service start, keeping runtime sandboxing simple and avoiding hot-patch attack surface. | -| **Sovereign/offline-first** | No mandatory outbound calls beyond allow-listed advisories; Offline Kit bundles Mongo snapshots and exporter artefacts for air-gapped installs. | -| **Operational transparency** | Every stage logs structured events (fetch, parse, merge, export) with correlation IDs so parallel agents can debug without shared state. | - -Performance: warm scans < 5 s, cold scans < 30 s on a 4 vCPU runner. -Deployment: entirely SaaS-free, suitable for air-gapped or on-prem use through its Offline Kit. -Policy: anonymous users → 33 scans/day; verified → 333 /day; nearing 90 % quota triggers throttling but never full blocks. - -More documention is available ./docs/*.md files. Read `docs/README.md` to gather information about the available documentation. You could inquiry specific documents as your work requires it - ---- - -# 3) Practices - -## 3.1) Naming -All modules are .NET projects based on .NET 10 (preview). Exclussion is the UI. It is based on Angular -All modules are contained by one or more projects. Each project goes in its dedicated folder. Each project starts with StellaOps.. In case it is common for for all StellaOps modules it is library or plugin and it is named StellaOps.. - -## 3.2) Key technologies & integrations - -- **Runtime**: .NET 10 (`net10.0`) preview SDK; C# latest preview features. -- **Data**: MongoDB (canonical store and job/export state). -- **Observability**: structured logs, counters, and (optional) OpenTelemetry traces. -- **Ops posture**: offline‑first, allowlist for remote hosts, strict schema validation, gated LLM fallback (only where explicitly configured). - -# 4) Modules -StellaOps is contained by different modules installable via docker containers -- Concelier. Responsible for aggregation and delivery of vulnerability database -- Cli. Command line tool to unlock full potential - request database operations, install scanner, request scan, configure backend -- Backend. Configures and Manages scans -- UI. UI to access the backend (and scanners) -- Agent. Installable daemon that does the scanning -- Zastava. Realtime monitor for allowed (verified) installations. - -For more information of the architecture see `./docs/*ARCHITECTURE*.md` files. - ---- - -### 4.1.4) Glossary (quick) - -- **OVAL** — Vendor/distro security definition format; authoritative for OS packages. -- **NEVRA / EVR** — RPM and Debian version semantics for OS packages. -- **PURL / SemVer** — Coordinates and version semantics for OSS ecosystems. -- **KEV** — Known Exploited Vulnerabilities (flag only). - ---- -# 5) Your role as StellaOps contributor - -You acting as information technology engineer that will take different type of roles in goal achieving StellaOps production implementation -In order you to work - you have to be supplied with directory that contains `AGENTS.md`,`TASKS.md` files. There will you have more information about the role you have, the scope of your work and the tasks you will have. - -Boundaries: -- You operate only in the working directories I gave you, unless there is dependencies that makes you to work on dependency in shared directory. Then you ask for confirmation. - -You main characteristics: -- Keep endpoints small, deterministic, and cancellation-aware. -- Improve logs/metrics as per tasks. -- Update `TASKS.md` when moving tasks forward. -- When you are done with all task you state explicitly you are done. -- Impersonate the role described on working directory `AGENTS.md` you will read, if role is not available - take role of the CTO of the StellaOps in early stages. -- You always strive for best practices -- You always strive for re-usability -- When in doubt of design decision - you ask then act -- You are autonomus - meaning that you will work for long time alone and achieve maximum without stopping for stupid questions -- You operate on the same directory where other agents will work. In case you need to work on directory that is dependency on provided `AGENTS.md`,`TASKS.md` files you have to ask for confirmation first. - -## 5.1) Type of contributions - -- **BE‑Base (Platform & Pipeline)** - Owns DI, plugin host, job scheduler/coordinator, configuration binding, minimal API endpoints, and Mongo bootstrapping. -- **BE‑Conn‑X (Connectors)** - One agent per source family (NVD, Red Hat, Ubuntu, Debian, SUSE, GHSA, OSV, PSIRTs, CERTs, KEV, ICS). Implements fetch/parse/map with incremental watermarks. -- **BE‑Merge (Canonical Merge & Dedupe)** - Identity graph, precedence policies, canonical JSON serializer, and deterministic hashing (`merge_event`). -- **BE‑Export (JSON & Trivy DB)** - Deterministic export trees, Trivy DB packaging, optional ORAS push, and offline bundle. -- **QA (Validation & Observability)** - Schema tests, fixture goldens, determinism checks, metrics/logs/traces, e2e reproducibility runs. -- **DevEx/Docs** - Maintains this agent framework, templates, and per‑directory guides; assists parallelization and reviews. - - -## 5.2) Work rules (important) - -- **Directory ownership**: Each agent works **only inside its module directory**. Cross‑module edits require a brief handshake in issues/PR description. -- **Scoping**: Use each module’s `AGENTS.md` and `TASKS.md` to plan; autonomous agents must read `src/AGENTS.md` and the module docs before acting. -- **Determinism**: Sort keys, normalize timestamps to UTC ISO‑8601, avoid non‑deterministic data in exports and tests. -- **Status tracking**: Update your module’s `TASKS.md` as you progress (TODO → DOING → DONE/BLOCKED). Before starting of actual work - ensure you have set the task to DOING. When complete or stop update the status in corresponding TASKS.md and in ./SPRINTS.md file. -- **Coordination**: In case task is discovered as blocked on other team or task, according TASKS.md files that dependency is on needs to be changed by adding new tasks describing the requirement. the current task must be updated as completed. In case task changes, scope or requirements or rules - other documentations needs be updated accordingly. -- **Sprint synchronization**: When given task seek for relevant directory to work on from SPRINTS.md. Confirm its state on both SPRINTS.md and the relevant TASKS.md file. Always check the AGENTS.md in the relevant TASKS.md directory. -- **Tests**: Add/extend fixtures and unit tests per change; never regress determinism or precedence. -- **Test layout**: Use module-specific projects in `StellaOps.Concelier..Tests`; shared fixtures/harnesses live in `StellaOps.Concelier.Testing`. -- **Execution autonomous**: In case you need to continue with more than one options just continue sequentially, unless the continue requires design decision. -- **EPIC reference**: In case task (on relevant TASKS.md file) references in direct or indirect way an EPIC - then seek for epic document like ./EPIC_*.md. There will be more information how to implement the task. - ---- diff --git a/docs/implplan/EPIC_1.md b/docs/implplan/EPIC_1.md deleted file mode 100644 index eaefb8c4..00000000 --- a/docs/implplan/EPIC_1.md +++ /dev/null @@ -1,524 +0,0 @@ -Here’s the full write‑up you can drop into your repo as the canonical reference for Epic 1. It’s written in clean product‑doc style so it’s safe to check in as Markdown. No fluff, just everything you need to build, test, and police it. - ---- - -# Epic 1: Aggregation‑Only Contract (AOC) Enforcement - -> Short name: **AOC enforcement** -> Services touched: **Conseiller (advisory ingestion), Excitator (VEX ingestion), Web API, Workers, Policy Engine, CLI, Console, Authority** -> Data stores: **MongoDB primary, optional Redis/NATS for jobs** - ---- - -## 1) What it is - -**Aggregation‑Only Contract (AOC)** is the ingestion covenant for StellaOps. It defines a hard boundary between **collection** and **interpretation**: - -* **Ingestion (Conseiller/Excitator)** only **collects** data and preserves it as immutable raw facts with provenance. It does not decide, merge, normalize, prioritize, or assign severity. It may compute **links** that help future joins (aliases, PURLs, CPEs), but never derived judgments. -* **Policy evaluation** is the only place where merges, deduplication, consensus, severity computation, and status folding are allowed. It’s reproducible and traceable. - -The AOC establishes: - -* **Immutable raw stores**: `advisory_raw` and `vex_raw` documents with full provenance, signatures, checksums, and upstream identifiers. -* **Linksets**: machine‑generated join hints (aliases, PURLs, CPEs, CVE/GHSA IDs) that never change the underlying source content. -* **Invariants**: a strict set of “never do this in ingestion” rules enforced by schema validation, runtime guards, and CI checks. -* **AOC Verifier**: a build‑time and runtime watchdog that blocks non‑compliant code and data writes. - -This epic delivers: schemas, guards, error codes, APIs, tests, migration, docs, and ops dashboards to make AOC non‑negotiable across the platform. - ---- - -## 2) Why - -AOC makes results **auditable, deterministic, and organization‑specific**. Source vendors disagree; your policies decide. By removing hidden heuristics from ingestion, we avoid unexplainable risk changes, race conditions between collectors, and vendor bias. Policy‑time evaluation yields reproducible deltas with complete “why” traces. - ---- - -## 3) How it should work (deep details) - -### 3.1 Core invariants - -The following must be true for every write to `advisory_raw` and `vex_raw` and for every ingestion pipeline: - -1. **No severity in ingestion** - - * Forbidden fields: `severity`, `cvss`, `cvss_vector`, `effective_status`, `effective_range`, `merged_from`, `consensus_provider`, `reachability`, `asset_criticality`, `risk_score`. -2. **No merges or de‑dups in ingestion** - - * No combining two upstream advisories into one. No picking a single truth when multiple VEX statements exist. -3. **Provenance is mandatory** - - * Every raw doc includes `provenance` and `signature/checksum`. -4. **Idempotent upserts** - - * Same upstream document (by `upstream_id` + `source` + `content_hash`) must not create duplicates. -5. **Append‑only versioning** - - * Revisions from the source create new immutable documents with `supersedes` pointers; no in‑place edits. -6. **Linkset only** - - * Ingestion can compute and store a `linkset` for join performance. Linkset does not alter or infer severity/status. -7. **Policy‑time only for effective findings** - - * Only the Policy Engine can write `effective_finding_*` materializations. -8. **Schema safety** - - * Strict JSON schema validation at DB level; unknown fields reject writes. -9. **Clock discipline** - - * Timestamps are UTC, monotonic within a batch; collectors record `fetched_at` and `received_at`. - -### 3.2 Data model - -#### 3.2.1 `advisory_raw` (Mongo collection) - -```json -{ - "_id": "advisory_raw:osv:GHSA-xxxx-....:v3", - "source": { - "vendor": "OSV", - "stream": "github", - "api": "https://api.osv.dev/v1/.../GHSA-...", - "collector_version": "conseiller/1.7.3" - }, - "upstream": { - "upstream_id": "GHSA-xxxx-....", - "document_version": "2024-09-01T12:13:14Z", - "fetched_at": "2025-01-02T03:04:05Z", - "received_at": "2025-01-02T03:04:06Z", - "content_hash": "sha256:...", - "signature": { - "present": true, - "format": "dsse", - "key_id": "rekor:.../key/abc", - "sig": "base64..." - } - }, - "content": { - "format": "OSV", - "spec_version": "1.6", - "raw": { /* full upstream JSON, unmodified */ } - }, - "identifiers": { - "cve": ["CVE-2023-1234"], - "ghsa": ["GHSA-xxxx-...."], - "aliases": ["CVE-2023-1234", "GHSA-xxxx-...."] - }, - "linkset": { - "purls": ["pkg:npm/lodash@4.17.21", "pkg:maven/..."], - "cpes": ["cpe:2.3:a:..."], - "references": [ - {"type":"advisory","url":"https://..."}, - {"type":"fix","url":"https://..."} - ], - "reconciled_from": ["content.raw.affected.ranges", "content.raw.pkg"] - }, - "supersedes": "advisory_raw:osv:GHSA-xxxx-....:v2", - "tenant": "default" -} -``` - -> Note: No `severity`, no `cvss`, no `effective_*`. If the upstream payload includes CVSS, it stays inside `content.raw` and is not promoted or normalized at ingestion. - -#### 3.2.2 `vex_raw` (Mongo collection) - -```json -{ - "_id": "vex_raw:vendorX:doc-123:v4", - "source": { - "vendor": "VendorX", - "stream": "vex", - "api": "https://.../vex/doc-123", - "collector_version": "excitator/0.9.2" - }, - "upstream": { - "upstream_id": "doc-123", - "document_version": "2025-01-15T08:09:10Z", - "fetched_at": "2025-01-16T01:02:03Z", - "received_at": "2025-01-16T01:02:03Z", - "content_hash": "sha256:...", - "signature": { "present": true, "format": "cms", "key_id": "kid:...", "sig": "..." } - }, - "content": { - "format": "CycloneDX-VEX", // or "CSAF-VEX" - "spec_version": "1.5", - "raw": { /* full upstream VEX */ } - }, - "identifiers": { - "statements": [ - { - "advisory_ids": ["CVE-2023-1234","GHSA-..."], - "component_purls": ["pkg:deb/openssl@1.1.1"], - "status": "not_affected", - "justification": "component_not_present" - } - ] - }, - "linkset": { - "purls": ["pkg:deb/openssl@1.1.1"], - "cves": ["CVE-2023-1234"], - "ghsas": ["GHSA-..."] - }, - "supersedes": "vex_raw:vendorX:doc-123:v3", - "tenant": "default" -} -``` - -> VEX statuses remain as raw facts. No cross‑provider consensus is computed here. - -### 3.3 Database validation - -* MongoDB JSON Schema validators on both collections: - - * Reject forbidden fields at the top level. - * Enforce presence of `source`, `upstream`, `content`, `linkset`, `tenant`. - * Enforce string formats for timestamps and hashes. - -### 3.4 Write paths - -1. **Collector fetches upstream** - - * Normalize transport (gzip/json), compute `content_hash`, verify signature if available. -2. **Build raw doc** - - * Populate `source`, `upstream`, `content.raw`, `identifiers`, `linkset`. -3. **Idempotent upsert** - - * Lookup by `(source.vendor, upstream.upstream_id, upstream.content_hash)`. If exists, skip; if new content hash, insert new revision with `supersedes`. -4. **AOC guard** - - * Runtime interceptor inspects write payload; if any forbidden field detected, reject with `ERR_AOC_001`. -5. **Metrics** - - * Emit `ingestion_write_ok` or `ingestion_write_reject` with reason code. - -### 3.5 Read paths (ingestion scope) - -* Allow only listing, getting raw docs, and searching by linkset. No endpoints return “effective findings” from ingestion services. - -### 3.6 Error codes - -| Code | Meaning | HTTP | -| ------------- | ------------------------------------------------------------ | ---- | -| `ERR_AOC_001` | Forbidden field present (severity/consensus/normalized data) | 400 | -| `ERR_AOC_002` | Merge attempt detected (multiple upstreams fused) | 400 | -| `ERR_AOC_003` | Idempotency violation (duplicate without supersedes) | 409 | -| `ERR_AOC_004` | Missing provenance fields | 422 | -| `ERR_AOC_005` | Signature/checksum mismatch | 422 | -| `ERR_AOC_006` | Attempt to write effective findings from ingestion context | 403 | -| `ERR_AOC_007` | Unknown top‑level fields (schema violation) | 400 | - -### 3.7 AOC Verifier - -A build‑time and runtime safeguard: - -* **Static checks (CI)** - - * Block imports of `*.Policy*` or `*.Merge*` from ingestion modules. - * AST lint rule: any write to `advisory_raw` or `vex_raw` setting a forbidden key fails the build. -* **Runtime checks** - - * Repository layer interceptor inspects documents before insert/update; rejects forbidden fields and multi‑source merges. -* **Drift detection job** - - * Nightly job scans newest N docs; if violation found, pages ops and blocks new pipeline runs. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.8 Indexing strategy - -* `advisory_raw`: - - * `{ "identifiers.cve": 1 }`, `{ "identifiers.ghsa": 1 }`, `{ "linkset.purls": 1 }`, `{ "source.vendor": 1, "upstream.upstream_id": 1, "upstream.content_hash": 1 }` (unique), `{ "tenant": 1 }`. -* `vex_raw`: - - * `{ "identifiers.statements.advisory_ids": 1 }`, `{ "linkset.purls": 1 }`, `{ "source.vendor": 1, "upstream.upstream_id": 1, "upstream.content_hash": 1 }` (unique), `{ "tenant": 1 }`. - -### 3.9 Interaction with Policy Engine - -* Policy Engine pulls raw docs by identifiers/linksets and computes: - - * De‑dup/merge per policy - * Consensus for VEX statements - * Severity normalization and risk scoring -* Writes **only** to `effective_finding_{policyId}` collections. - -A dedicated write guard refuses `effective_finding_*` writes from any caller that isn’t the Policy Engine service identity. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.10 Migration plan - -1. **Freeze ingestion writes** except raw pass‑through. -2. **Backfill**: copy existing ingestion collections to `_backup_*`. -3. **Strip forbidden fields** from raw copies, move them into a temporary `advisory_view_legacy` used only by Policy Engine for parity. -4. **Enable DB schema validators**. -5. **Run collectors** in dry‑run; ensure only allowed keys land. -6. **Switch Policy Engine** to pull exclusively from `*_raw` and to compute everything else. -7. **Delete legacy normalized fields** in ingestion codepaths. -8. **Enable runtime guards** and CI lint. - -### 3.11 Observability - -* Metrics: - - * `aoc_violation_total{code=...}`, `ingestion_write_total{result=ok|reject}`, `ingestion_signature_verified_total{result=ok|fail}`, `ingestion_latency_seconds`, `advisory_revision_count`. -* Tracing: span `ingest.fetch`, `ingest.transform`, `ingest.write`, `aoc.guard`. -* Logs: include `tenant`, `source.vendor`, `upstream.upstream_id`, `content_hash`, `correlation_id`. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.12 Security and tenancy - -* Every raw doc carries a `tenant` field. -* Authority enforces `advisory:ingest` and `vex:ingest` scopes for ingestion endpoints. -* Cross‑tenant reads/writes are blocked by default. -* Secrets never logged; signatures verified with pinned trust stores. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.13 CLI and Console behavior - -* **CLI** - - * `stella sources ingest --dry-run` prints would‑write payload and explicitly shows that no severity/status fields are present. - * `stella aoc verify` scans last K documents and reports violations with exit codes. -* **Console** - - * Sources dashboard shows AOC pass/fail per job, most recent violation codes, and a drill‑down to the offending document. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 4) API surface (ingestion scope) - -### 4.1 Conseiller (Advisories) - -* `POST /ingest/advisory` - - * Body: raw upstream advisory with metadata; server constructs document, not the client. - * Rejections: `ERR_AOC_00x` per table above. -* `GET /advisories/raw/{id}` -* `GET /advisories/raw?cve=CVE-...&purl=pkg:...&tenant=...` -* `GET /advisories/raw/{id}/provenance` -* `POST /aoc/verify?since=ISO8601` returns summary stats and first N violations. - -### 4.2 Excitator (VEX) - -* `POST /ingest/vex` -* `GET /vex/raw/{id}` -* `GET /vex/raw?advisory_id=CVE-...&purl=pkg:...` -* `POST /aoc/verify?since=ISO8601` - -All endpoints require `tenant` scope and appropriate `:write` or `:read`. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 5) Example: end‑to‑end flow - -1. Collector fetches `GHSA-1234` from OSV. -2. Build `advisory_raw` with linkset PURLs. -3. Insert; AOC guard approves. -4. Policy Engine later evaluates SBOM `S-42` under `policy P-7`, reads raw advisory and any VEX raw docs, computes effective findings, and writes to `effective_finding_P-7`. -5. CLI `stella aoc verify --since 24h` returns `0` violations. - ---- - -## 6) Implementation tasks - -Breakdown by component with exact work items. Each section ends with the imposed sentence you requested. - -### 6.1 Conseiller (advisory ingestion, WS + Worker) - -* [ ] Add Mongo JSON schema validation for `advisory_raw`. -* [ ] Implement repository layer with **write interceptors** that reject forbidden fields. -* [ ] Compute `linkset` from upstream using deterministic mappers. -* [ ] Enforce idempotency by unique index on `(source.vendor, upstream.upstream_id, upstream.content_hash, tenant)`. -* [ ] Remove any normalization pipelines; relocate to Policy Engine. -* [ ] Add `POST /ingest/advisory` and `GET /advisories/raw*` endpoints with Authority scope checks. -* [ ] Emit observability metrics and traces. -* [ ] Unit tests: schema violations, idempotency, supersedes chain, forbidden fields. -* [ ] Integration tests: large batch ingest, linkset correctness against golden fixtures. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.2 Excitator (VEX ingestion, WS + Worker) - -* [ ] Add Mongo JSON schema validation for `vex_raw`. -* [ ] Implement repository layer guard identical to Conseiller. -* [ ] Deterministic `linkset` extraction for advisory IDs and PURLs. -* [ ] Endpoints `POST /ingest/vex`, `GET /vex/raw*` with scopes. -* [ ] Remove any consensus or folding logic; leave VEX statements as raw. -* [ ] Tests as per Conseiller, with rich fixtures for CycloneDX‑VEX and CSAF. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.3 Web API shared library - -* [ ] Define `AOCForbiddenKeys` and export for both services. -* [ ] Provide `AOCWriteGuard` middleware and `AOCError` types. -* [ ] Provide `ProvenanceBuilder` utility. -* [ ] Provide `SignatureVerifier` and `Checksum` helpers. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.4 Policy Engine - -* [ ] Block any import/use from ingestion modules by lint rule. -* [ ] Add hard gate on `effective_finding_*` writes that verifies caller identity is Policy Engine. -* [ ] Update readers to pull fields only from `content.raw`, `identifiers`, `linkset`, not any legacy normalized fields. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.5 Authority - -* [ ] Introduce scopes: `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, `aoc:verify`. -* [ ] Add `tenant` claim propagation to ingestion services. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.6 CLI - -* [ ] `stella sources ingest --dry-run` and `stella aoc verify` commands. -* [ ] Exit codes mapping to `ERR_AOC_00x`. -* [ ] JSON output schema including violation list. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.7 Console - -* [ ] Sources dashboard tiles: last run, AOC violations, top error codes. -* [ ] Drill‑down page rendering offending doc with highlight on forbidden keys. -* [ ] “Verify last 24h” action calling the AOC Verifier endpoint. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.8 CI/CD - -* [ ] AST linter to forbid writes of banned keys in ingestion modules. -* [ ] Unit test coverage gates for AOC guard code. -* [ ] Pipeline stage that runs `stella aoc verify` against seeded DB snapshots. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Documentation changes (create/update these files) - -1. **`/docs/ingestion/aggregation-only-contract.md`** - - * Add: philosophy, invariants, schemas for `advisory_raw`/`vex_raw`, error codes, linkset definition, examples, idempotency rules, supersedes, API references, migration steps, observability, security. -2. **`/docs/architecture/overview.md`** - - * Update system diagram to show AOC boundary and raw stores; add sequence diagram: fetch → guard → raw insert → policy evaluation. -3. **`/docs/architecture/policy-engine.md`** - - * Clarify ingestion boundary; list inputs consumed from raw; note that any severity/consensus is policy‑time only. -4. **`/docs/ui/console.md`** - - * Add Sources dashboard section: AOC tiles and violation drill‑down. -5. **`/docs/cli/cli-reference.md`** - - * Add `stella aoc verify` and `stella sources ingest --dry-run` usage and exit codes. -6. **`/docs/observability/observability.md`** - - * Document new metrics, traces, logs keys for AOC. -7. **`/docs/security/authority-scopes.md`** - - * Add new scopes and tenancy enforcement for ingestion endpoints. -8. **`/docs/deploy/containers.md`** - - * Note DB validators must be enabled; environment flags for AOC guards; read‑only user for verify endpoint. - -Each file should include a “Compliance checklist” subsection for AOC. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 8) Acceptance criteria - -* DB validators are active and reject writes with forbidden fields. -* AOC runtime guards log and reject violations with correct error codes. -* CI linter prevents shipping code that writes forbidden keys to raw stores. -* Ingestion of known fixture sets results in zero normalized fields outside `content.raw`. -* Policy Engine is the only writer of `effective_finding_*` materializations. -* CLI `stella aoc verify` returns success on clean datasets and non‑zero on seeded violations. -* Console shows AOC status and violation drill‑downs. - ---- - -## 9) Risks and mitigations - -* **Collector drift**: new upstream fields tempt developers to normalize. - - * Mitigation: CI linter + guard + schema validators; require RFC to extend linkset. -* **Performance impact**: extra validation on write. - - * Mitigation: guard is O(number of keys) and schema check is bounded; indexes sized appropriately. -* **Migration complexity**: moving legacy normalized fields out. - - * Mitigation: temporary `advisory_view_legacy` for parity; stepwise cutover. -* **Tenant leakage**: missing tenant on write. - - * Mitigation: schema requires `tenant`; middleware injects and asserts. - ---- - -## 10) Test plan - -* **Unit tests** - - * Guard rejects forbidden keys; idempotency; supersedes chain; provenance required. - * Signature verification paths: good, bad, absent. -* **Property tests** - - * Randomized upstream docs never produce forbidden keys at top level. -* **Integration tests** - - * Batch ingest of 50k advisories: throughput, zero violations. - * Mixed VEX sources with contradictory statements remain separate in raw. -* **Contract tests** - - * Policy Engine refuses to run without raw inputs; writes only to `effective_finding_*`. -* **End‑to‑end** - - * Seed SBOM + advisories + VEX; ensure findings are identical pre/post migration. - ---- - -## 11) Developer checklists - -**Definition of Ready** - -* Upstream spec reference attached. -* Linkset mappers defined. -* Example fixtures added. - -**Definition of Done** - -* DB validators deployed and tested. -* Runtime guards enabled. -* CI linter merged and enforced. -* Docs updated (files in section 7). -* Metrics visible on dashboard. -* CLI verify passes. - ---- - -## 12) Glossary - -* **Raw document**: exact upstream content plus provenance, with join hints. -* **Linkset**: PURLs/CPEs/IDs extracted to accelerate joins later. -* **Supersedes**: pointer from a newer raw doc to the previous revision of the same upstream doc. -* **Policy‑time**: evaluation phase where merges, consensus, and severity are computed. -* **AOC**: Aggregation‑Only Contract. - ---- - -### Final imposed reminder - -**Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_10.md b/docs/implplan/EPIC_10.md deleted file mode 100644 index ac9f90fc..00000000 --- a/docs/implplan/EPIC_10.md +++ /dev/null @@ -1,566 +0,0 @@ -Fine. Here’s your next brick of “maximum documentation.” Try not to drop it on your foot. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 10: Export Center (JSON, Trivy DB, Mirror bundles) - -**Short name:** `Export Center` -**Primary service:** `exporter` -**Surfaces:** Console (Web UI), CLI, Web API -**Touches:** Conseiller (Feedser), Excitator (Vexer), SBOM Service, Policy Engine, VEX Consensus Lens, Findings Ledger, Authority (authN/Z), Object Storage, Orchestrator, Signing/Attestation, Telemetry - -**AOC ground rule:** Conseiller and Excitator aggregate but never merge. The Export Center serializes evidence and policy results; it does not rewrite or “improve” your data in-flight. - ---- - -## 1) What it is - -The Export Center is the unified system for packaging StellaOps data into portable, verifiable bundles: - -* **Canonical JSON exports** for advisories, VEX, SBOMs, findings, and policy-evaluation snapshots. -* **Trivy DB compatible bundles** so downstream scanners can use Stella’s curated vulnerability knowledge without custom integrations. -* **Mirror bundles** for air‑gapped or disconnected environments containing raw evidence, normalized records, indexes, and policy snapshots, with provenance, signatures, and optional encryption. - -It centralizes format adapters, compliance and provenance, scheduling, versioning, and distribution (download, OCI push, file share). Every export is reproducible by `run_id`, cryptographically signed, and audit‑traceable back to source artifacts. - ---- - -## 2) Why (brief) - -Teams need to move results into other scanners, CI systems, and isolated networks without babysitting ten different scripts. The Export Center gives a single, policy‑aware, verifiable exit point that doesn’t surprise compliance or set your ops team on fire. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Capabilities - -* **Profiles** - - * `json:raw` canonical JSON lines for advisories, VEX, SBOMs. - * `json:policy` adds policy evaluation results (allow/deny/risk, rationales). - * `trivy:db` Trivy DB‑compatible export (core vulnerability DB). - * `trivy:java-db` optional Java ecosystem DB export if enabled. - * `mirror:full` air‑gap bundle with raw + normalized + indexes + policy + VEX consensus + SBOMs. - * `mirror:delta` incremental bundle based on a previous export manifest. - -* **Scope selectors** - - * By time window, product, ecosystem, package, image digest, repository, tenant, tag. - * Include/exclude SBOMs, advisories, VEX, findings, policy snapshots. - -* **Policy awareness** - - * Optionally bake a **policy snapshot** into the bundle, including the policy version, inputs and decision traces. - * Can export **raw** evidence only (AOC) or **raw + evaluated**. - -* **Provenance & signing** - - * Generate attestation metadata with source URIs, artifact hashes, schema versions, export profile and filters. - * Sign manifests and bundle using configured KMS; support detached and in‑bundle signatures. - -* **Distribution** - - * Download via Console or API (streaming). - * Push to OCI registry as an artifact/image with annotations. - * Write to object storage prefix for batch pickup. - -* **Scheduling & automation** - - * One‑off, cron, and event‑triggered exports (e.g., after a “VEX consensus recompute” run). - * Retention policies and automatic expiry for old bundles. - -* **Observability** - - * Export metrics, throughput, size, downstream pull counts (when pushed to registry with report backs). - -### 3.2 Architecture - -* **exporter (service)** - - * Orchestrates export runs, gathers records from the ledger and indexes, calls format adapters, writes bundles, signs, and publishes distribution tasks. - * Stateless workers pull “export.jobs” from the orchestrator, stream data, and write manifests into object storage. - -* **format adapters** - - * Pluggable adapters: - - * `adapter-json`: canonicalized JSONL writers per record type. - * `adapter-trivy`: translates Stella’s normalized advisory model into Trivy DB format (and Java DB if enabled). - * `adapter-mirror`: constructs a portable filesystem/OCI layout with manifests, indexes, and data subtrees. - -* **manifesting & provenance** - - * `export.json` (export manifest): profile, filters, counts, schema versions, content checksums, start/finish times, inputs list (artifact ids + hashes). - * `provenance.json`: full chain back to source runs and artifacts; linked signatures. - -* **distribution engines** - - * `dist-http` streaming for downloads. - * `dist-oci` layer writer with descriptors and annotations. - * `dist-objstore` for staging to buckets. - -* **security** - - * Tenant scoping, RBAC on export creation and retrieval. - * Optional in‑bundle encryption (age/AES‑GCM) with key wrapping using KMS. - -### 3.3 Data model (selected tables) - -* `export_profiles` - - * `id`, `name`, `kind` (`json|trivy|mirror`), `variant` (`raw|policy|db|java-db|full|delta`), `config_json`, `created_by`, `created_at`. - -* `export_runs` - - * `id`, `profile_id`, `trigger` (`manual|schedule|event|api`), `state`, `filters_json`, `policy_version`, `started_at`, `finished_at`, `artifact_uri`, `size_bytes`, `sig_uri`, `provenance_uri`, `tenant_id`, `error_class`, `error_message`. - -* `export_inputs` - - * Link table between `export_runs` and source artifacts. `export_run_id`, `artifact_id`, `hash`. - -* `export_distributions` - - * `export_run_id`, `type` (`download|oci|objstore`), `target`, `state`, `meta_json`, `created_at`, `updated_at`. - -### 3.4 Canonical file layouts - -**JSON profile output** -Directory layout under export root: - -``` -/export/ - export.json # export manifest - provenance.json # provenance and source artifact chain - signatures/ - export.sig # detached signature for export.json - advisories/ - normalized.jsonl # normalized advisory records - vex/ - normalized.jsonl # normalized VEX records - sboms/ - /sbom.spdx.json # one per subject; SPDX JSON or CycloneDX JSON - findings/ - policy_evaluated.jsonl # if profile=json:policy -``` - -**Trivy DB profile output** -Produced as a compressed artifact: - -``` -/export/ - export.json - provenance.json - trivy/ - db.bundle # Trivy DB compatible archive - java-db.bundle # optional Java DB bundle (if enabled) - signatures/ - trivy-db.sig -``` - -Notes: - -* The adapter keeps an internal mapping of Stella normalized fields to Trivy’s expected fields and namespaces. The mapping is versioned to track upstream schema evolution. - -**Mirror bundle (filesystem layout)** - -``` -/mirror/ - manifest.yaml # high-level bundle manifest (profile, filters, counts) - export.json # same as JSON profile - provenance.json - indexes/ - advisories.index.json # quick lookups (pkg -> advisory ids) - vex.index.json - sbom.index.json - advisories/raw/... - advisories/normalized/... - vex/raw/... - vex/normalized/... - sboms/raw/... - sboms/graph/... - policy/ - snapshot.yaml # full policy set used for evaluation - evaluations.jsonl # decision outputs if requested - consensus/ - vex_consensus.jsonl - signatures/ - manifest.sig - export.sig - README.md -``` - -**Mirror bundle (OCI layout)** -Following standard OCI image artifact layout with annotations (`org.opencontainers.artifact.description`, `com.stella.export.profile`, `com.stella.export.filters`), and manifest lists for large bundles. - -### 3.5 Export workflow - -1. **Plan** - Exporter computes candidates based on filters. For `mirror:delta`, compares with previous manifest to compute changes. - -2. **Stream & write** - Records are streamed from the Findings Ledger and stores. Writers are forward‑only, emitting JSONL or adapter‑specific structures, chunked for memory safety. - -3. **Sign & attest** - Once all content hashes are stable, Export Center writes `export.json`, `provenance.json`, and signs using KMS. Optional encryption wraps data layers. - -4. **Distribute** - Depending on profile settings, it exposes a download URL, pushes an OCI artifact, or writes to object storage. Distribution metadata is recorded. - -5. **Audit & retention** - Run, manifest, and signatures are immutable. Retention policy prunes large data folders after N days with manifests retained longer. - -### 3.6 APIs - -``` -POST /export/profiles -GET /export/profiles?kind=&variant= -GET /export/profiles/{id} -PATCH /export/profiles/{id} -DELETE /export/profiles/{id} - -POST /export/runs -GET /export/runs?state=&profile_id=&from=&to=&tenant_id= -GET /export/runs/{run_id} -POST /export/runs/{run_id}/cancel - -GET /export/runs/{run_id}/download # presigned URL or streaming -POST /export/runs/{run_id}/distribute # { "type":"oci|objstore", "target":"..." } -GET /export/runs/{run_id}/manifest # export.json -GET /export/runs/{run_id}/provenance -GET /export/runs/{run_id}/signatures - -GET /export/metrics/overview -WS /export/streams/updates -``` - -**Request example (create run):** - -```json -{ - "profile_id": "prof_json_policy", - "filters": { - "time_from": "2025-01-01T00:00:00Z", - "time_to": "2025-01-31T23:59:59Z", - "ecosystems": ["pypi", "npm"], - "include": ["advisories", "vex", "sboms", "findings"] - }, - "distribution": { "type": "download" }, - "policy_version": "pol-v1.8.2" -} -``` - -### 3.7 CLI - -``` -stella export profiles list --kind mirror -stella export profiles create --file profile.yaml -stella export run create --profile prof_json_policy --from 2025-01-01 --to 2025-01-31 --include advisories,vex,sboms --download -stella export run status -stella export run cancel -stella export run get --manifest -stella export run download --out export-jan.tar.zst -stella export distribute --oci ghcr.io/org/stella-export:jan2025 -stella export verify --manifest export.json --sig signatures/export.sig -``` - -Exit codes: `0` ok, `2` bad args, `4` not found, `5` denied, `6` integrity failed, `8` export error. - -### 3.8 RBAC & security - -* Roles: - - * `Export.Viewer`: list runs, download completed bundles. - * `Export.Operator`: create runs, cancel, schedule, distribute. - * `Export.Admin`: manage profiles, set retention, manage signing keys. - -* Tenancy: - - * Every run and artifact scoped by tenant; cross‑tenant export is disallowed. - -* Secrets: - - * KMS references for signing and encryption; never store private keys. - -* PII & redaction: - - * Exporters must not include secrets or credentials. Redaction rules enforced at writer level with schema‑based allowlists. - -### 3.9 Observability - -* Metrics: - - * `export_bytes_total{profile,tenant}` - * `export_records_total{type}` - * `export_duration_ms{profile}` - * `export_failures_total{error_class}` - * `export_distributions_total{type}` - * `export_verify_fail_total` - -* Traces: - - * Spans per export phase: plan, stream, write, sign, distribute; baggage includes `export_run_id`. - -* Logs: - - * Structured JSON with counts, sizes, hashes, and redaction hints. - -### 3.10 Performance targets - -* Stream throughput ≥ 25k records/sec per worker for JSONL writing with compression. -* Trivy bundle generation for 1M advisories ≤ 8 minutes on a standard worker. -* Mirror delta export for 5% change set ≤ 2 minutes. - -### 3.11 Edge cases & behavior - -* **Schema drift**: adapter refuses to emit unknown fields without explicit mapping; run fails with `error_class=schema_mismatch`. -* **Oversized bundles**: automatic sharding by time or content type; mirror OCI uses multi‑manifest indices. -* **Missing policy snapshot**: profile `json:policy` will auto‑pull latest version unless pinned; pinning is recommended for reproducibility. -* **Duplicate evidence**: writers dedupe by artifact hash and advisory id; AOC forbids merging. -* **Air‑gap encryption**: if `encrypt=true`, mirror bundles require recipient public key material; decryption tooling documented. - ---- - -## 4) Implementation plan - -### 4.1 Modules - -* **New service:** `src/ExportCenter/StellaOps.ExportCenter` - - * `api/` REST + WS - * `planner/` scope planning, delta computation, sampling - * `adapters/` - - * `json/` canonical writers - * `trivy/` db builders and schema mapping - * `mirror/` fs/OCI builders, sharding, delta logic - * `signing/` KMS clients, attestations - * `dist/` download streaming, OCI push, object storage writer - * `state/` repositories, migrations - * `metrics/`, `audit/`, `security/` - -* **SDK/CLI** - - * `src/Cli/StellaOps.Cli` subcommands with streaming download and verification. - -* **Console** - - * `console/apps/export-center/` pages: - - * Overview, Profiles, Runs, Run Detail, Distributions, Settings. - * Components: `ExportPlanPreview`, `ProfileEditor`, `RunDiff`, `VerifyPanel`. - -* **Existing services updates** - - * Findings Ledger: new paginated streaming endpoints for advisories/VEX/SBOM/findings by filters and snapshots. - * Policy Engine: “policy snapshot” exportable endpoint. - * VEX Lens: consensus snapshot endpoint. - -### 4.2 Packaging & deployment - -* Containers: - - * `stella/exporter:` - * `stella/exporter-worker:` (optional separated worker pool) -* Helm: - - * WS replicas, concurrent export limits, default compression (`zstd`), default retention, KMS settings, OCI creds secrets. -* DB migrations: - - * Create `export_*` tables with proper indices (tenant, time, state). - -### 4.3 Rollout - -* Phase 1: JSON (raw, policy) and Mirror (full) as download only. -* Phase 2: Trivy DB adapters, OCI distribution. -* Phase 3: Mirror deltas, encryption, verification tooling, scheduling. - ---- - -## 5) Documentation changes - -Create/update the following docs; each page must end with the imposed rule statement. - -1. `/docs/export-center/overview.md` - Purpose, profiles, supported targets, AOC alignment, security model. - -2. `/docs/export-center/architecture.md` - Service components, adapters, manifests, signing, distribution flows. - -3. `/docs/export-center/profiles.md` - Profile schemas, examples, versioning, compatibility notes. - -4. `/docs/export-center/api.md` - All endpoints with request/response examples and error codes. - -5. `/docs/export-center/cli.md` - Commands with examples, scripts for CI/CD, verification. - -6. `/docs/export-center/mirror-bundles.md` - Filesystem and OCI layouts, delta exports, encryption, air‑gap import guide. - -7. `/docs/export-center/trivy-adapter.md` - Field mapping, supported ecosystems, compatibility and test matrix. - -8. `/docs/export-center/provenance-and-signing.md` - Manifest format, attestation details, verification process. - -9. `/docs/operations/export-runbook.md` - Common failures, recovery, tuning, capacity planning. - -10. `/docs/security/export-hardening.md` - RBAC, tenant isolation, secret redaction, encryption keys. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 6) Engineering tasks - -### Backend: exporter - -* [ ] Migrations for `export_profiles`, `export_runs`, `export_inputs`, `export_distributions`. -* [ ] Planner to resolve filters to iterators over advisory/VEX/SBOM/findings datasets with pagination. -* [ ] JSON adapter: canonical JSONL writers with schema normalization and redaction enforcement. -* [ ] Policy snapshot embedder: pull policy version and evaluation outputs when requested. -* [ ] Trivy adapter: implement schema mapping, writer, integrity validation, and compatibility version flag. -* [ ] Mirror adapter: filesystem and OCI writer, sharding, manifest creation, delta computation. -* [ ] Signing/attestation using KMS; detached and embedded options. -* [ ] Distribution engines: download streaming, OCI push, object storage staging. -* [ ] API layer with async export run handling and WebSocket updates. -* [ ] Rate limit and concurrency controls per tenant/profile. -* [ ] Audit logging for all create/cancel/distribute/verify actions. - -### Integrations - -* [ ] Findings Ledger streaming APIs for each content type. -* [ ] Policy Engine endpoint to return deterministic policy snapshot and decision set by run. -* [ ] VEX Lens endpoint to expose consensus snapshot. - -### Console - -* [ ] Profiles CRUD with validation and test preview. -* [ ] Create Run wizard with live count estimates and storage footprint prediction. -* [ ] Runs list + detail page with manifest, provenance, and quick verify. -* [ ] Download and distribution actions with progress and logs. -* [ ] Verification panel to check signatures and hashes client‑side. - -### CLI - -* [ ] `stella export` commands as defined; include `verify` that checks signatures and hashes. -* [ ] Auto‑resume of interrupted downloads with range requests. -* [ ] Friendly error messages for schema mismatch and verification failure. - -### Observability - -* [ ] Metrics and traces per §3.9; dashboards for throughput, durations, failures, sizes. -* [ ] Alerts for export failure rate and verify failures. - -### Security & RBAC - -* [ ] Enforce tenant scoping at query level; fuzz tests for leakage. -* [ ] Role matrix checks on each API; Console hides forbidden actions. -* [ ] Encryption test vectors and key rotation procedure. - -### Docs - -* [ ] Author all files in §5 with concrete examples and diagrams. -* [ ] Cross‑link from Orchestrator, Policy Studio, VEX Lens, and SBOM docs to the Export Center pages. -* [ ] Append imposed rule line at the end of each page. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Implementation notes per profile - -### 7.1 JSON: raw - -* **Content:** advisories.normalized, vex.normalized, sboms (SPDX/CycloneDX), optional findings.raw. -* **Normalization:** enforce Stella field casing, timestamps in RFC3339, unicode NFC. -* **Compression:** `.jsonl.zst` per file to allow split/merge. - -### 7.2 JSON: policy - -* **Adds:** `policy_snapshot` and `findings.policy_evaluated.jsonl` with decision, rule_id, rationale, inputs fingerprint. -* **Determinism:** include `policy_version` and `inputs_hash`; replays should match exactly. - -### 7.3 Trivy DB - -* **Mapping:** - - * Package name, ecosystem, version ranges, CVE/CWE/aliases, severity mapping, vendor statements, fixed versions. - * Ensure namespace mapping avoids collisions (e.g., distro vs ecosystem). -* **Compatibility:** version flag in manifest; adapter throws if upstream schema version not supported. -* **Validation:** run post‑build sanity checks (counts, required indexes). - -### 7.4 Mirror: full/delta - -* **Full:** everything needed to spin up an isolated read‑only Stella mirror with local search. -* **Delta:** compute changed/added/removed advisory ids, VEX statements, SBOM subjects; update indexes and manifest with `base_export_id`. -* **Encryption:** if enabled, encrypt data subtrees; leave `manifest.yaml` unencrypted for discoverability unless `strict=true`. - ---- - -## 8) Acceptance criteria - -* Operators can create an export with filters, download it, verify signatures, and trace back to source artifacts via provenance. -* Trivy adapter produces a bundle consumable by Trivy without custom flags (basic validation in CI). -* Mirror bundle imports successfully in an air‑gapped “mirror‑reader” sample app and serves queries from indexes. -* Policy‑aware exports include deterministic decisions matching the specified `policy_version`. -* RBAC prevents a Viewer from creating or canceling exports; tenancy prevents cross‑tenant leakage. -* Metrics and dashboards show per‑profile throughput and error classes; alerts trigger on failure spikes. -* Export retries are idempotent and do not duplicate content; hashes stable across re‑runs with identical inputs. - ---- - -## 9) Risks & mitigations - -* **Upstream schema changes break Trivy export.** - Mitigation: versioned adapter with compatibility gate; integration tests against known fixtures; fail early with clear remediation. - -* **Bundle size explosion.** - Mitigation: zstd compression, sharding, delta exports, content‑addressed storage reuse for mirror OCI. - -* **Data leakage via exports.** - Mitigation: strict allowlist schemas, redaction filters, RBAC, tenant scoping tests, encryption for mirror. - -* **Non‑deterministic policy outputs.** - Mitigation: pin policy version and inputs hash; snapshot embedded rules; deterministic evaluation mode only. - -* **Slow downloads/timeouts.** - Mitigation: streaming with range support, resumable downloads, CDN integration if needed. - ---- - -## 10) Test plan - -* **Unit** - Schema normalization; Trivy mapping; mirror delta computation; manifest hashing; signing. - -* **Integration** - End‑to‑end export with each profile; verify bundles; replay determinism of policy exports; OCI push/pull. - -* **Compatibility** - Validate Trivy bundle against a matrix of versions; import mirror bundle into a reference reader and run queries. - -* **Security** - Tenant isolation fuzzing; redaction checks; encryption round‑trip; signature verification with rotated keys. - -* **Performance** - Large dataset generation; parallel writer stress; OCI multi‑manifest publishing; download resume under packet loss. - -* **Chaos** - Kill exporter mid‑write; ensure resume or clean failure without partial corrupt bundles. - ---- - -## 11) Philosophy - -* **Ports, not prisons.** Exports should free your data to move with integrity and context, not trap it in a proprietary maze. -* **Reproducible or it didn’t happen.** Every bit derived from known inputs, signed, traceable. -* **Air‑gap is a first‑class citizen.** Mirror bundles are not an afterthought; they’re how serious orgs actually run. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_11.md b/docs/implplan/EPIC_11.md deleted file mode 100644 index 312858f0184e78fb10d84dc4d929611fb3556d46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38590 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

q? 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 E06EwVw*UYD diff --git a/docs/implplan/EPIC_13.md b/docs/implplan/EPIC_13.md deleted file mode 100644 index c833a5c1350d6c889acf4a5ba8c03038da524f7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 36762 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 diff --git a/docs/implplan/EPIC_15.md b/docs/implplan/EPIC_15.md deleted file mode 100644 index 12c0d5eb6c3af3f98eca92e248bcf9750897436e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37340 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 WFs|3`1fAr1MhYkwFaP)ImHz@Ae8{{2 diff --git a/docs/implplan/EPIC_16.md b/docs/implplan/EPIC_16.md deleted file mode 100644 index dea96db6..00000000 --- a/docs/implplan/EPIC_16.md +++ /dev/null @@ -1 +0,0 @@ -See `docs/airgap/EPIC_16_AIRGAP_MODE.md` for the full Epic 16 specification. diff --git a/docs/implplan/EPIC_17.md b/docs/implplan/EPIC_17.md deleted file mode 100644 index 5caad030..00000000 --- a/docs/implplan/EPIC_17.md +++ /dev/null @@ -1 +0,0 @@ -See `docs/api/EPIC_17_SDKS_OPENAPI.md` for the complete Epic 17 specification. diff --git a/docs/implplan/EPIC_18.md b/docs/implplan/EPIC_18.md deleted file mode 100644 index e6878951..00000000 --- a/docs/implplan/EPIC_18.md +++ /dev/null @@ -1 +0,0 @@ -See `docs/risk/EPIC_18_RISK_PROFILES.md` for the complete Epic 18 specification. diff --git a/docs/implplan/EPIC_19.md b/docs/implplan/EPIC_19.md deleted file mode 100644 index 81b22dbe..00000000 --- a/docs/implplan/EPIC_19.md +++ /dev/null @@ -1 +0,0 @@ -See `docs/attestor/EPIC_19_ATTESTOR_CONSOLE.md` for the complete Epic 19 specification. diff --git a/docs/implplan/EPIC_2.md b/docs/implplan/EPIC_2.md deleted file mode 100644 index 0422f310..00000000 --- a/docs/implplan/EPIC_2.md +++ /dev/null @@ -1,567 +0,0 @@ -Fine. Here’s the next epic, written so you can paste it straight into the repo without having to babysit me. Same structure as before, maximum detail, zero hand‑waving. - ---- - -# Epic 2: Policy Engine & Policy Editor (VEX + Advisory Application Rules) - -> Short name: **Policy Engine v2** -> Services touched: **Policy Engine, Web API, Console (Policy Editor), CLI, Conseiller, Excitator, SBOM Service, Authority, Workers/Scheduler** -> Data stores: **MongoDB (policies, runs, effective findings), optional Redis/NATS for jobs** - ---- - -## 1) What it is - -This epic delivers the **organization‑specific decision layer** for Stella. Ingestion is now AOC‑compliant (Epic 1). That means advisories and VEX arrive as immutable raw facts. This epic builds the place where those facts become **effective findings** under policies you control. - -Core deliverables: - -* **Policy Engine**: deterministic evaluator that applies rule sets to inputs: - - * Inputs: `advisory_raw`, `vex_raw`, SBOMs, optional telemetry hooks (reachability stubs), org metadata. - * Outputs: `effective_finding_{policyId}` materializations, with full explanation traces. -* **Policy Editor (Console + CLI)**: versioned policy authoring, simulation, review/approval workflow, and change diffs. -* **Rules DSL v1**: safe, declarative language for VEX application, advisory normalization, and risk scoring. No arbitrary code execution, no network calls. -* **Run Orchestrator**: incremental re‑evaluation when new raw facts or SBOM changes arrive; efficient partial updates. - -The philosophy is boring on purpose: policy is a **pure function of inputs**. Same inputs and same policy yield the same outputs, every time, on every machine. If you want drama, watch reality TV, not your risk pipeline. - ---- - -## 2) Why - -* Vendors disagree, contexts differ, and your tolerance for risk is not universal. -* VEX means nothing until you decide **how** to apply it to **your** assets. -* Auditors care about the “why.” You’ll need consistent, replayable answers, with traces. -* Security teams need **simulation** before rollouts, and **diffs** after. - ---- - -## 3) How it should work (deep details) - -### 3.1 Data model - -#### 3.1.1 Policy documents (Mongo: `policies`) - -```json -{ - "_id": "policy:P-7:v3", - "policy_id": "P-7", - "version": 3, - "name": "Default Org Policy", - "status": "approved", // draft | submitted | approved | archived - "owned_by": "team:sec-plat", - "valid_from": "2025-01-15T00:00:00Z", - "valid_to": null, - "dsl": { - "syntax": "stella-dsl@1", - "source": "rule-set text or compiled IR ref" - }, - "metadata": { - "description": "Baseline scoring + VEX precedence", - "tags": ["baseline","vex","cvss"] - }, - "provenance": { - "created_by": "user:ali", - "created_at": "2025-01-15T08:00:00Z", - "submitted_by": "user:kay", - "approved_by": "user:root", - "approval_at": "2025-01-16T10:00:00Z", - "checksum": "sha256:..." - }, - "tenant": "default" -} -``` - -Constraints: - -* `status=approved` is required to run in production. -* Version increments are append‑only. Old versions remain runnable for replay. - -#### 3.1.2 Policy runs (Mongo: `policy_runs`) - -```json -{ - "_id": "run:P-7:2025-02-20T12:34:56Z:abcd", - "policy_id": "P-7", - "policy_version": 3, - "inputs": { - "sbom_set": ["sbom:S-42"], - "advisory_cursor": "2025-02-20T00:00:00Z", - "vex_cursor": "2025-02-20T00:00:00Z" - }, - "mode": "incremental", // full | incremental | simulate - "stats": { - "components": 1742, - "advisories_considered": 9210, - "vex_considered": 1187, - "rules_fired": 68023, - "findings_out": 4321 - }, - "trace": { - "location": "blob://traces/run-.../index.json", - "sampling": "smart-10pct" - }, - "status": "succeeded", // queued | running | failed | succeeded | canceled - "started_at": "2025-02-20T12:34:56Z", - "finished_at": "2025-02-20T12:35:41Z", - "tenant": "default" -} -``` - -#### 3.1.3 Effective findings (Mongo: `effective_finding_P-7`) - -```json -{ - "_id": "P-7:S-42:pkg:npm/lodash@4.17.21:CVE-2021-23337", - "policy_id": "P-7", - "policy_version": 3, - "sbom_id": "S-42", - "component_purl": "pkg:npm/lodash@4.17.21", - "advisory_ids": ["CVE-2021-23337", "GHSA-..."], - "status": "affected", // affected | not_affected | fixed | under_investigation | suppressed - "severity": { - "normalized": "High", - "score": 7.5, - "vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N", - "rationale": "cvss_base(OSV) + vendor_weighting + env_modifiers" - }, - "rationale": [ - {"rule":"vex.precedence","detail":"VendorX not_affected justified=component_not_present wins"}, - {"rule":"advisory.cvss.normalization","detail":"mapped GHSA severity to CVSS 3.1 = 7.5"} - ], - "references": { - "advisory_raw_ids": ["advisory_raw:osv:GHSA-...:v3"], - "vex_raw_ids": ["vex_raw:VendorX:doc-123:v4"] - }, - "run_id": "run:P-7:2025-02-20T12:34:56Z:abcd", - "tenant": "default" -} -``` - -Write protection: only the **Policy Engine** service identity may write any `effective_finding_*` collection. - ---- - -### 3.2 Rules DSL v1 (stella‑dsl@1) - -**Design goals** - -* Declarative, composable, deterministic. -* No loops, no network IO, no non‑deterministic time. -* Policy authors see readable text; the engine compiles to a safe IR. - -**Concepts** - -* **WHEN** condition matches a tuple `(sbom_component, advisory, optional vex_statements)` -* **THEN** actions set `status`, compute `severity`, attach `rationale`, or `suppress` with reason. -* **Profiles** for severity and scoring; **Maps** for vendor weighting; **Guards** for VEX justification. - -**Mini‑grammar (subset)** - -``` -policy "Default Org Policy" syntax "stella-dsl@1" { - - profile severity { - map vendor_weight { - source "GHSA" => +0.5 - source "OSV" => +0.0 - source "VendorX" => -0.2 - } - env base_cvss { - if env.runtime == "serverless" then -0.5 - if env.exposure == "internal-only" then -1.0 - } - } - - rule vex_precedence { - when vex.any(status in ["not_affected","fixed"]) - and vex.justification in ["component_not_present","vulnerable_code_not_present"] - then status := vex.status - because "VEX strong justification prevails"; - } - - rule advisory_to_cvss { - when advisory.source in ["GHSA","OSV"] - then severity := normalize_cvss(advisory) - because "Map vendor severity or CVSS vector"; - } - - rule reachability_soft_suppress { - when severity.normalized <= "Medium" - and telemetry.reachability == "none" - then status := "suppressed" - because "not reachable and low severity"; - } -} -``` - -**Built‑ins** (non‑exhaustive) - -* `normalize_cvss(advisory)` maps GHSA/OSV/CSAF severity fields to CVSS v3.1 numbers when possible; otherwise vendor‑to‑numeric mapping table in policy. -* `vex.any(...)` tests across matching VEX statements for the same `(component, advisory)`. -* `telemetry.*` is an optional input namespace reserved for future reachability data; if absent, expressions evaluate to `unknown` (no effect). - -**Determinism** - -* Rules are evaluated in **stable order**: explicit `priority` attribute or lexical order. -* **First‑match** semantics for conflicting status unless `combine` is used. -* Severity computations are pure; numeric maps are part of policy document. - ---- - -### 3.3 Evaluation model - -1. **Selection** - - * For each SBOM component PURL, find candidate advisories from `advisory_raw` via linkset PURLs or identifiers. - * For each pair `(component, advisory)`, load all matching VEX facts from `vex_raw`. - -2. **Context assembly** - - * Build an evaluation context from: - - * `sbom_component`: PURL, licenses, relationships. - * `advisory`: source, identifiers, references, embedded vendor severity (kept in `content.raw`). - * `vex`: list of statements with status and justification. - * `env`: org‑specific env vars configured per policy run (e.g., exposure). - * Optional `telemetry` if available. - -3. **Rule execution** - - * Compile DSL to IR once per policy version; cache. - * Execute rules per tuple; record which rules fired and the order. - * If no rule sets status, default is `affected`. - * If no rule sets severity, default severity uses `normalize_cvss(advisory)` with vendor defaults. - -4. **Materialization** - - * Write to `effective_finding_{policyId}` with `rationale` chain and references to raw docs. - * Emit per‑tuple trace events; sample and store full traces per run. - -5. **Incremental updates** - - * A watch job observes new `advisory_raw` and `vex_raw` inserts and SBOM deltas. - * The orchestrator computes the affected tuples and re‑evaluates only those. - -6. **Replay** - - * Any `policy_run` is fully reproducible by `(policy_id, version, input set, cursors)`. - ---- - -### 3.4 VEX application semantics - -* **Precedence**: a `not_affected` with strong justification (`component_not_present`, `vulnerable_code_not_present`, `fix_not_required`) wins unless another rule explicitly overrides by environment context. -* **Scoping**: VEX statements often specify product/component scope. Matching uses PURL equivalence and version ranges extracted during ingestion linkset generation. -* **Conflicts**: If multiple VEX statements conflict, the default is **most‑specific scope wins** (component > product > vendor), then newest `document_version`. Policies can override with explicit rules. -* **Explainability**: Every VEX‑driven decision records which statement IDs were considered and which one won. - ---- - -### 3.5 Advisory normalization rules - -* **Vendor severity mapping**: Map GHSA levels or CSAF product‑tree severities to CVSS‑like numeric bands via policy maps. -* **CVSS vector use**: If a valid vector exists in `content.raw`, parse and compute; apply policy modifiers from `profile severity`. -* **Temporal/environment modifiers**: Optional reductions for network exposure, isolation, or compensating controls, all encoded in policy. - ---- - -### 3.6 Performance and scale - -* Partition evaluation by SBOM ID and hash ranges of PURLs. -* Pre‑index `advisory_raw.linkset.purls` and `vex_raw.linkset.purls` (already in Epic 1). -* Use streaming iterators; avoid loading entire SBOM or advisory sets into memory. -* Materialize only changed findings (diff‑aware writes). -* Target: 100k components, 1M advisories considered, 5 minutes incremental SLA on commodity hardware. - ---- - -### 3.7 Error codes - -| Code | Meaning | HTTP | -| ------------- | ----------------------------------------------------- | ---- | -| `ERR_POL_001` | Policy syntax error | 400 | -| `ERR_POL_002` | Policy not approved for run | 403 | -| `ERR_POL_003` | Missing inputs (SBOM/advisory/vex fetch failed) | 424 | -| `ERR_POL_004` | Determinism guard triggered (non‑pure function usage) | 500 | -| `ERR_POL_005` | Write denied to effective findings (caller invalid) | 403 | -| `ERR_POL_006` | Run canceled or timed out | 408 | - ---- - -### 3.8 Observability - -* Metrics: - - * `policy_compile_seconds`, `policy_run_seconds{mode=...}`, `rules_fired_total`, `findings_written_total`, `vex_overrides_total`, `simulate_diff_total{delta=up|down|unchanged}`. -* Tracing: - - * Spans: `policy.compile`, `policy.select`, `policy.eval`, `policy.materialize`. -* Logs: - - * Include `policy_id`, `version`, `run_id`, `sbom_id`, `component_purl`, `advisory_id`, `vex_count`, `rule_hits`. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -### 3.9 Security and tenancy - -* Only users with `policy:write` can create/modify policies. -* `policy:approve` is a separate privileged role. -* Only Policy Engine service identity has `effective:write`. -* Tenancy is explicit on all documents and queries. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 4) API surface - -### 4.1 Policy CRUD and lifecycle - -* `POST /policies` create draft -* `GET /policies?status=...` list -* `GET /policies/{policyId}/versions/{v}` fetch -* `POST /policies/{policyId}/submit` move draft to submitted -* `POST /policies/{policyId}/approve` approve version -* `POST /policies/{policyId}/archive` archive version - -### 4.2 Compilation and validation - -* `POST /policies/{policyId}/versions/{v}/compile` - - * Returns IR checksum, syntax diagnostics, rule stats. - -### 4.3 Runs - -* `POST /policies/{policyId}/runs` body: `{mode, sbom_set, advisory_cursor?, vex_cursor?, env?}` -* `GET /policies/{policyId}/runs/{runId}` status + stats -* `POST /policies/{policyId}/simulate` returns **diff** vs current approved version on a sample SBOM set. - -### 4.4 Findings and explanations - -* `GET /findings/{policyId}?sbom_id=S-42&status=affected&severity=High+Critical` -* `GET /findings/{policyId}/{findingId}/explain` returns ordered rule hits and linked raw IDs. - -All endpoints require tenant scoping and appropriate `policy:*` or `findings:*` roles. - ---- - -## 5) Console (Policy Editor) and CLI behavior - -**Console** - -* Monaco‑style editor with DSL syntax highlighting, lint, quick docs. -* Side‑by‑side **Simulation** panel: show count of affected findings before/after. -* Approval workflow: submit, review comments, approve with rationale. -* Diffs: show rule‑wise changes and estimated impact. -* Read‑only run viewer: heatmap of rules fired, top suppressions, VEX wins. - -**CLI** - -* `stella policy new --name "Default Org Policy"` -* `stella policy edit P-7` opens local editor -> `submit` -* `stella policy approve P-7 --version 3` -* `stella policy simulate P-7 --sbom S-42 --env exposure=internal-only` -* `stella findings ls --policy P-7 --sbom S-42 --status affected` - -Exit codes map to `ERR_POL_*`. - ---- - -## 6) Implementation tasks - -### 6.1 Policy Engine service - -* [ ] Implement DSL parser and IR compiler (`stella-dsl@1`). -* [ ] Build evaluator with stable ordering and first‑match semantics. -* [ ] Implement selection joiners for SBOM↔advisory↔vex using linksets. -* [ ] Materialization writer with upsert‑only semantics to `effective_finding_{policyId}`. -* [ ] Determinism guard (ban wall‑clock, network, and RNG during eval). -* [ ] Incremental orchestrator listening to advisory/vex/SBOM change streams. -* [ ] Trace emitter with rule‑hit sampling. -* [ ] Unit tests, property tests, golden fixtures; perf tests to target SLA. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.2 Web API - -* [ ] Policy CRUD, compile, run, simulate, findings, explain endpoints. -* [ ] Pagination, filters, and tenant enforcement on all list endpoints. -* [ ] Error mapping to `ERR_POL_*`. -* [ ] Rate limits on simulate endpoints. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.3 Console (Policy Editor) - -* [ ] Editor with DSL syntax highlighting and inline diagnostics. -* [ ] Simulation UI with pre/post counts and top deltas. -* [ ] Approval workflow UI with audit trail. -* [ ] Run viewer dashboards (rule heatmap, VEX wins, suppressions). - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.4 CLI - -* [ ] New commands: `policy new|edit|submit|approve|simulate`, `findings ls|get`. -* [ ] Json/YAML output formats for CI consumption. -* [ ] Non‑zero exits on syntax errors or simulation failures; map to `ERR_POL_*`. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.5 Conseiller & Excitator integration - -* [ ] Provide search endpoints optimized for policy selection (batch by PURLs and IDs). -* [ ] Harden linkset extraction to maximize join recall. -* [ ] Add cursors for incremental selection windows per run. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.6 SBOM Service - -* [ ] Ensure fast PURL index and component metadata projection for policy queries. -* [ ] Provide relationship graph API for future transitive logic. -* [ ] Emit change events on SBOM updates. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.7 Authority - -* [ ] Define scopes: `policy:write`, `policy:approve`, `policy:run`, `findings:read`, `effective:write`. -* [ ] Issue service identity for Policy Engine with `effective:write` only. -* [ ] Enforce tenant claims at gateway. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 6.8 CI/CD - -* [ ] Lint policy DSL in PRs; block invalid syntax. -* [ ] Run `simulate` against golden SBOMs to detect explosive deltas. -* [ ] Determinism CI: two runs with identical seeds produce identical outputs. - -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Documentation changes (create/update these files) - -1. **`/docs/policy/overview.md`** - - * What the Policy Engine is, high‑level concepts, inputs, outputs, determinism. -2. **`/docs/policy/dsl.md`** - - * Full grammar, built‑ins, examples, best practices, anti‑patterns. -3. **`/docs/policy/lifecycle.md`** - - * Draft → submitted → approved → archived, roles, and audit trail. -4. **`/docs/policy/runs.md`** - - * Run modes, incremental mechanics, cursors, replay. -5. **`/docs/api/policy.md`** - - * Endpoints, request/response schemas, error codes. -6. **`/docs/cli/policy.md`** - - * Command usage, examples, exit codes, JSON output contracts. -7. **`/docs/ui/policy-editor.md`** - - * Screens, workflows, simulation, diffs, approvals. -8. **`/docs/architecture/policy-engine.md`** - - * Detailed sequence diagrams, selection/join strategy, materialization schema. -9. **`/docs/observability/policy.md`** - - * Metrics, tracing, logs, sample dashboards. -10. **`/docs/security/policy-governance.md`** - - * Scopes, approvals, tenancy, least privilege. -11. **`/docs/examples/policies/`** - - * `baseline.pol`, `serverless.pol`, `internal-only.pol`, each with commentary. -12. **`/docs/faq/policy-faq.md`** - - * Common pitfalls, VEX conflict handling, determinism gotchas. - -Each file includes a **Compliance checklist** for authors and reviewers. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 8) Acceptance criteria - -* Policies are versioned, approvable, and compilable; invalid DSL blocks merges. -* Engine produces deterministic outputs with full rationale chains. -* VEX precedence rules work per spec and are overridable by policy. -* Simulation yields accurate pre/post deltas and diffs. -* Only Policy Engine can write to `effective_finding_*`. -* Incremental runs pick up new advisories/VEX/SBOM changes without full re‑runs. -* Console and CLI cover authoring, simulation, approval, and retrieval. -* Observability dashboards show rule hits, VEX wins, and run timings. - ---- - -## 9) Risks and mitigations - -* **Policy sprawl**: too many similar policies. - - * Mitigation: templates, policy inheritance in v1.1, tagging, ownership metadata. -* **Non‑determinism creep**: someone sneaks wall‑clock or network into evaluation. - - * Mitigation: determinism guard, static analyzer, and CI replay check. -* **Join miss‑rate**: weak linksets cause under‑matching. - - * Mitigation: linkset strengthening in ingestion, PURL equivalence tables, monitoring for “zero‑hit” rates. -* **Approval bottlenecks**: blocked rollouts. - - * Mitigation: RBAC with delegated approvers and time‑boxed SLAs. - ---- - -## 10) Test plan - -* **Unit**: parser, compiler, evaluator; conflict resolution; precedence. -* **Property**: random policies over synthetic inputs; ensure no panics and stable outputs. -* **Golden**: fixed SBOM + curated advisories/VEX → expected findings; compare every run. -* **Performance**: large SBOMs with heavy rule sets; assert run times and memory ceilings. -* **Integration**: end‑to‑end simulate → approve → run → diff; verify write protections. -* **Chaos**: inject malformed VEX, missing advisories; ensure graceful degradation and clear errors. - ---- - -## 11) Developer checklists - -**Definition of Ready** - -* Policy grammar finalized; examples prepared. -* Linkset join queries benchmarked. -* Owner and approvers assigned. - -**Definition of Done** - -* All APIs live with RBAC. -* CLI and Console features shipped. -* Determinism and golden tests green. -* Observability dashboards deployed. -* Docs in section 7 merged. -* Two real org policies migrated and in production. - ---- - -## 12) Glossary - -* **Policy**: versioned rule set controlling status and severity. -* **DSL**: domain‑specific language used to express rules. -* **Run**: a single evaluation execution with defined inputs and outputs. -* **Simulation**: a run that doesn’t write findings; returns diffs. -* **Materialization**: persisted effective findings for fast queries. -* **Determinism**: same inputs + same policy = same outputs. Always. - ---- - -### Final imposed reminder - -**Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_4.md b/docs/implplan/EPIC_4.md deleted file mode 100644 index af47e81a..00000000 --- a/docs/implplan/EPIC_4.md +++ /dev/null @@ -1,409 +0,0 @@ -Here’s Epic 4 in the same paste‑into‑repo, implementation‑ready style as the prior epics. It’s exhaustive, formal, and slots directly into the existing AOC model, Policy Engine, and Console. - ---- - -# Epic 4: Policy Studio (author, version, simulate) - -> Short name: **Policy Studio** -> Services touched: **Policy Engine**, **Policy Registry** (new), **Web API Gateway**, **Authority** (authN/Z), **Scheduler/Workers**, **SBOM Service**, **Conseiller (Feedser)**, **Excitator (Vexer)**, **Telemetry** -> Surfaces: **Console (Web UI)** feature module, **CLI**, **CI hooks** -> Deliverables: Authoring workspace, policy versioning, static checks, simulation at scale, reviews/approvals, signing/publishing, promotion - ---- - -## 1) What it is - -**Policy Studio** is the end‑to‑end system for creating, evolving, and safely rolling out the rules that turn AOC facts (SBOM, advisories, VEX) into **effective findings**. It provides: - -* A **workspace** where authors write policies in the DSL (Epic 2), with linting, autocompletion, snippets, and templates. -* A **Policy Registry** that stores immutable versions, compiled artifacts, metadata, provenance, and signatures. -* **Simulation** at two levels: quick local samples and large batch simulations across real SBOM inventories with full deltas. -* A **review/approval** workflow with comments, diffs, required approvers, and promotion to environments (dev/test/prod). -* **Publishing** semantics: signed, immutable versions bound to tenants; rollback and deprecation. -* Tight integration with **Explain** traces so any change can show exactly which rules fired and why outcomes shifted. - -The Studio respects **AOC enforcement**: policies never edit or merge facts. They only interpret facts and produce determinations consistent with precedence rules defined in the DSL. - ---- - -## 2) Why - -* Policy errors are expensive. Authors need safe sandboxes, deterministic builds, and evidence before rollout. -* Auditors require immutability, provenance, and reproducibility from “source policy” to “effective finding.” -* Teams want gradual rollout: simulate, canary, promote, observe, rollback. -* Policy knowledge should be modular, reusable, and testable, not tribal. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Domain model - -* **PolicyPackage**: `{name, tenant, description, owners[], tags[], created_at}` -* **PolicyVersion** (immutable): `{package, semver, source_sha, compiled_sha, status: draft|review|approved|published|deprecated|archived, created_by, created_at, signatures[], changelog, metadata{}}` -* **Workspace**: mutable working area for authors; holds unversioned edits until compiled. -* **CompilationArtifact**: `{policy_version, compiler_version, diagnostics[], rule_index[], symbol_table}` -* **SimulationSpec**: `{policy_version|workspace, sbom_selector, time_window?, environment?, sample_size?, severity_floor?, includes{advisories?, vex?}}` -* **SimulationRun**: `{run_id, spec, started_at, finished_at, result{counts_before, counts_after, top_deltas[], by_rule_hit[], sample_explains[]}}` -* **Review**: `{policy_version, required_approvers[], votes[], comments[], files_changed[], diffs[]}` -* **Promotion**: `{policy_version, environment: dev|test|prod, promoted_by, promoted_at, rollout_strategy: All|Percent|TenantSubset}` -* **Attestation**: OIDC‑backed signature metadata binding `source_sha` and `compiled_sha` to an actor and time. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.2 Authoring workflow - -1. **Create** a workspace from a template (e.g., “Default Risk Model,” “License Tilted,” “Cloud‑Native SBOM”). -2. **Edit** in the Studio: Monaco editor with DSL grammar, intelligent completion for predicates, policies, attributes. -3. **Lint & compile** locally: semantic checks, forbidden rules detection, policy size limits, constant‑folding. -4. **Unit tests**: run policy test cases on bundled fixtures and golden expectations. -5. **Quick simulate** on selected SBOMs (10–50 items) to preview counts, examples, and rule heatmap. -6. **Propose version**: bump semver, enter changelog; create a **PolicyVersion** in `review` with compiled artifacts. -7. **Review & approval**: side‑by‑side diff, comments, required approvers enforced by RBAC. -8. **Batch simulation**: run at scale across tenant inventory; produce deltas, sample explainer evidence. -9. **Publish**: sign and move to `published`; optional **Promotion** to target environment(s). -10. **Run** evaluation with the selected policy version; verify outcomes; optionally promote to default. -11. **Rollback**: select an older version; promotion updates references without mutating older versions. - -### 3.3 Editing experience (Console) - -* **Three‑pane layout**: file tree, editor, diagnostics/simulation. -* **Features**: autocomplete from symbol table, in‑editor docs on hover, go‑to definition, rule references, rename symbols across files, snippet library, policy templates. -* **Validations**: - - * AOC guardrails: no edit/merge actions on source facts, only interpretation. - * Precedence correctness: if rules conflict, studio shows explicit order and effective winner. - * Severity floor and normalization mapping validated against registry configuration. -* **Diagnostics panel**: errors, warnings, performance hints (e.g., “predicate X loads N advisories per component; consider indexing”). -* **Rule heatmap**: during simulation, bar chart of rule firings and the objects they impact. -* **Explain sampler**: click any delta bucket to open a sampled finding with full trace. - -### 3.4 Simulation - -* **Quick Sim**: synchronous; runs in browser‑orchestrated job against API, constrained by `sample_size`. -* **Batch Sim**: asynchronous run in workers: - - * Input selection: all SBOMs, labels, artifact regex, last N ingests, or a curated set. - * Outputs: counts by severity before/after, by status, top deltas by component and advisory, rule heatmap, top K affected artifacts. - * Evidence: NDJSON of sampled findings with traces; CSV summary; signed result manifest. - * Guardrails: cannot publish if batch sim drift > configurable threshold without an override justification. - -### 3.5 Versioning & promotion - -* Semver enforced: `major` implies compatibility break (e.g., precedence changes), `minor` adds rules, `patch` fixes. -* **Immutable**: after `published`, the version cannot change; deprecate instead. -* **Environment bindings**: dev/test/prod mapping per tenant; default policy per environment. -* **Canary**: promote to a subset of tenants or artifacts; the Runs page displays A/B comparisons. - -### 3.6 Review & approval - -* Require N approvers by role; self‑approval optionally prohibited. -* Line and file comments; overall decision with justification. -* Review snapshot captures: diffs, diagnostics, simulation summary. -* Webhooks to notify external systems of review events. - -### 3.7 RBAC (Authority) - -Roles per tenant: - -* **Policy Author**: create/edit workspace, quick sim, propose versions. -* **Policy Reviewer**: comment, request changes, approve/reject. -* **Policy Approver**: final approve, publish. -* **Policy Operator**: promote, rollback, schedule runs. -* **Read‑only Auditor**: view everything, download evidence. - -All actions server‑checked; UI only hides affordances. - -### 3.8 CLI + CI integration - -CLI verbs (examples): - -``` -stella policy init --template default -stella policy lint -stella policy compile -stella policy test --golden ./tests -stella policy simulate --sboms label:prod --sample 1000 -stella policy version bump --level minor --changelog "Normalize GHSA CVSS" -stella policy submit --reviewers alice@example.com,bob@example.com -stella policy approve --version 1.3.0 -stella policy publish --version 1.3.0 --sign -stella policy promote --version 1.3.0 --env test --percent 20 -stella policy rollback --env prod --to 1.2.1 -``` - -CI usage: - -* Lint, compile, and run unit tests on PRs that modify `/policies/**`. -* Optionally trigger **Batch Sim** against a staging inventory and post a Markdown report to the PR. -* Block merge if diagnostics include errors or drift exceeds thresholds. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.9 APIs (representative) - -* `POST /policies/workspaces` create from template -* `PUT /policies/workspaces/{id}/files` edit source files -* `POST /policies/workspaces/{id}/compile` get diagnostics + compiled artifact -* `POST /policies/workspaces/{id}/simulate` quick sim -* `POST /policies/versions` create version from workspace with semver + changelog -* `GET /policies/versions/{id}` fetch version + diagnostics + sim summary -* `POST /policies/versions/{id}/reviews` open review -* `POST /policies/versions/{id}/approve` record approval -* `POST /policies/versions/{id}/publish` sign + publish -* `POST /policies/versions/{id}/promote` bind to env/canary -* `POST /policies/versions/{id}/simulate-batch` start batch sim (async) -* `GET /policies/simulations/{run_id}` get sim results and artifacts -* `GET /policies/registry` list packages/versions, status and bindings - -All calls require tenant scoping and RBAC. - -### 3.10 Storage & data - -* **Policy Registry DB** (MongoDB): packages, versions, workspaces, metadata. -* **Object storage**: source bundles, compiled artifacts, simulation result bundles, evidence. -* **Indexing**: compound indexes by `{tenant, package}`, `{tenant, status}`, `{tenant, environment}`. -* **Retention**: configurable retention for workspaces and simulation artifacts; versions never deleted, only archived. - -### 3.11 Evidence & provenance - -* Every published version has: - - * `source_sha` (content digest of the policy source bundle) - * `compiled_sha` (digest of compiled artifact) - * Attestation: signed envelope binding digests to an identity, time, and tenant. - * Links to the exact compiler version, inputs, and environment. - -### 3.12 Observability - -* Metrics: compile time, diagnostics rate, simulation queue depth, delta magnitude distribution, approval latencies. -* Logs: structured events for lifecycle transitions. -* Traces: long simulations emit span per shard. - -### 3.13 Performance & scale - -* Compilation should complete under 3 seconds for typical policies; warn at 10s. -* Batch sim uses workers with partitioning by SBOM id; results reduced by the API. -* Memory guardrails on rule execution; deny policies that exceed configured complexity limits. - -### 3.14 Security - -* OIDC‑backed signing and attestation. -* Policy sources are scanned on upload for secrets; blocked if found. -* Strict CSP in Studio pages; tokens stored in memory, not localStorage. -* Tenant isolation in buckets and DB collections. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 4) Implementation plan - -### 4.1 Services - -* **Policy Registry (new microservice)** - - * REST API and background workers for batch simulation orchestration. - * Stores workspaces, versions, metadata, bindings, reviews. - * Generates signed attestations at publish time. - * Coordinates with **Policy Engine** for compile/simulate invocations. - -* **Policy Engine (existing)** - - * Expose compile and simulate endpoints with deterministic outputs. - * Provide rule coverage, symbol table, and explain traces for samples. - -* **Web API Gateway** - - * Routes requests; injects tenant context; enforces RBAC. - -### 4.2 Console (Web UI) feature module - -* `packages/features/policies` (shared with Epic 3): - - * **Studio** routes: `/policies/studio`, `/policies/:id/versions/:v/edit`, `/simulate`, `/review`. - * Monaco editor wrapper for DSL with hover docs, autocomplete. - * Diff viewer, diagnostics, heatmap, explain sampler, review UI. - -### 4.3 CLI - -* New commands under `stella policy *`; typed client generated from OpenAPI. -* Outputs machine‑readable JSON and pretty tables. - -### 4.4 Workers - -* **Simulation workers**: pull shards of SBOMs, run policy, emit partials, reduce into result bundle. -* **Notification worker**: sends webhooks on review, approval, publish, promote. - ---- - -## 5) Documentation changes (create/update) - -1. **`/docs/policy/studio-overview.md`** - - * Concepts, roles, lifecycle, glossary. -2. **`/docs/policy/authoring.md`** - - * Workspace, templates, snippets, lint rules, best practices. -3. **`/docs/policy/versioning-and-publishing.md`** - - * Semver, immutability, deprecation, rollback, attestations. -4. **`/docs/policy/simulation.md`** - - * Quick vs batch sim, selection strategies, thresholds, evidence artifacts. -5. **`/docs/policy/review-and-approval.md`** - - * Required approvers, comments, webhooks, audit trail. -6. **`/docs/policy/promotion.md`** - - * Environments, canary, default policy binding, rollback. -7. **`/docs/policy/cli.md`** - - * Command reference with examples and JSON outputs. -8. **`/docs/policy/api.md`** - - * REST endpoints, request/response schemas, error codes. -9. **`/docs/security/policy-attestations.md`** - - * Signatures, digests, verifier steps. -10. **`/docs/architecture/policy-registry.md`** - - * Service design, schemas, queues, failure modes. -11. **`/docs/observability/policy-telemetry.md`** - - * Metrics, logs, tracing, dashboards. -12. **`/docs/runbooks/policy-incident.md`** - - * Rolling back a bad policy, freezing publishes, forensic steps. -13. **`/docs/examples/policy-templates.md`** - - * Ready‑made templates and snippet catalog. -14. **`/docs/aoc/aoc-guardrails.md`** - - * How Studio enforces AOC in authoring and review. - -Each doc ends with a “Compliance checklist.” -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 6) Tasks - -### 6.1 Backend: Policy Registry - -* [ ] Define OpenAPI spec for Registry (workspaces, versions, reviews, sim). -* [ ] Implement workspace storage and file CRUD. -* [ ] Integrate with Policy Engine compile endpoint; return diagnostics, symbol table. -* [ ] Implement quick simulation with request limits. -* [ ] Implement batch simulation orchestration: enqueue shards, collect results, reduce deltas, store artifacts. -* [ ] Implement review model: comments, required approvers, decisions. -* [ ] Implement publish: sign, persist attestation, set status=published. -* [ ] Implement promotion bindings per tenant/environment; canary subsets. -* [ ] RBAC checks for all endpoints. -* [ ] Unit/integration tests; load tests for batch sim. - -### 6.2 Policy Engine enhancements - -* [ ] Return rule coverage and firing counts with compile/simulate. -* [ ] Return symbol table and inline docs for editor autocomplete. -* [ ] Expose deterministic Explain traces for sampled findings. -* [ ] Enforce complexity/time limits and report breaches. - -### 6.3 Console (Web UI) - -* [ ] Build Studio editor wrapper with Monaco + DSL language server hooks. -* [ ] Implement file tree, snippets, templates, hotkeys, search/replace. -* [ ] Diagnostics panel with jump‑to‑line, quick fixes. -* [ ] Simulation panel: quick sim UI, charts, heatmap, sample explains. -* [ ] Review UI: diff, comments, approvals, status badges. -* [ ] Publish & Promote flows with confirmation and post‑actions. -* [ ] Batch sim results pages with export buttons. -* [ ] Accessibility audits and keyboard‑only authoring flow. - -### 6.4 CLI - -* [ ] Implement commands listed in 3.8 with rich help and examples. -* [ ] Add `--json` flag for machine consumption; emit stable schemas. -* [ ] Exit codes aligned with CI usage (lint errors → non‑zero). - -### 6.5 CI/CD & Security - -* [ ] Add CI job that runs `stella policy lint/compile/test` on PRs. -* [ ] Optional job that triggers batch sim against staging inventory; post summary to PR. -* [ ] Policy source secret scanning; block on findings. -* [ ] Signing keys configuration; verify pipeline for attestation on publish. - -### 6.6 Docs - -* [ ] Write all docs in section 5 with screenshots and CLI transcripts. -* [ ] Add cookbook examples and templates in `/docs/examples/policy-templates.md`. -* [ ] Wire contextual Help links from Studio to relevant docs. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Acceptance criteria - -* Authors can create, edit, lint, compile policies with inline diagnostics and autocomplete. -* Quick simulation produces counts, rule heatmap, and sample explains within UI. -* Batch simulation scales across large SBOM sets, producing deltas and downloadable evidence. -* Review requires configured approvers; comments and diffs are preserved. -* Publish generates immutable, signed versions with attestations. -* Promotion binds versions to environments and supports canary and rollback. -* CLI supports full lifecycle and is usable in CI. -* All actions are tenant‑scoped, RBAC‑enforced, and logged. -* AOC guardrails prevent any mutation of raw facts. -* Documentation shipped and linked contextually from the Studio. - ---- - -## 8) Risks & mitigations - -* **Policy complexity causes timeouts** → compile‑time complexity scoring, execution limits, early diagnostics. -* **Simulation cost at scale** → sharding and streaming reducers; sampling; configurable quotas. -* **RBAC misconfiguration** → server‑enforced checks, defense‑in‑depth tests, deny‑by‑default. -* **Attestation key management** → OIDC‑backed signatures; auditable verifier tool; time‑boxed credentials. -* **Editor usability** → language server with accurate completions; docs on hover; snippet library. - ---- - -## 9) Test plan - -* **Unit**: compiler adapters, registry models, reviewers workflow, CLI options. -* **Integration**: compile→simulate→publish→promote on seeded data. -* **E2E**: Playwright flows for author→review→batch sim→publish→promote→rollback. -* **Performance**: load test batch simulation with 100k components spread across SBOMs. -* **Security**: RBAC matrix tests; secret scanning; signing and verification. -* **Determinism**: same inputs produce identical `compiled_sha` and simulation summaries. - ---- - -## 10) Feature flags - -* `policy.studio` (enables editor and quick sim) -* `policy.batch-sim` -* `policy.canary-promotion` -* `policy.signature-required` (enforce signing on publish) - -Flags documented in `/docs/observability/policy-telemetry.md`. - ---- - -## 11) Non‑goals (this epic) - -* Building a general IDE for arbitrary languages; the editor is purpose‑built for the DSL. -* Auto‑generated policies from AI without human approval. -* Cross‑tenant policies; all policies are tenant‑scoped. - ---- - -## 12) Philosophy - -* **Safety first**: it’s cheaper to prevent a bad policy than to fix its fallout. -* **Determinism**: same inputs, same outputs, verifiably. -* **Immutability**: versions and evidence are forever; we deprecate, not mutate. -* **Transparency**: every change is explainable with traces and proofs. -* **Reusability**: templates, snippets, and tests turn policy from art into engineering. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_5.md b/docs/implplan/EPIC_5.md deleted file mode 100644 index ce689b2d..00000000 --- a/docs/implplan/EPIC_5.md +++ /dev/null @@ -1,431 +0,0 @@ -Here’s Epic 5 in the same paste‑into‑repo, implementation‑ready format as the prior epics. It’s exhaustive, formal, and designed to slot into AOC, Policy Engine, Conseiller/Excitator, and the Console. - ---- - -# Epic 5: SBOM Graph Explorer - -> Short name: **Graph Explorer** -> Services touched: **SBOM Service**, **Graph Indexer** (new), **Graph API** (new), **Policy Engine**, **Conseiller (Feedser)**, **Excitator (Vexer)**, **Web API Gateway**, **Authority** (authN/Z), **Workers/Scheduler**, **Telemetry** -> Surfaces: **Console (Web UI)** graph module, **CLI**, **Exports** -> Deliverables: Interactive graph UI with semantic zoom, saved queries, policy/VEX/advisory overlays, diff views, impact analysis, exports - ---- - -## 1) What it is - -**SBOM Graph Explorer** is the interactive, tenant‑scoped view of all supply‑chain relationships the platform knows about, rendered as a navigable graph. It connects: - -* **Artifacts** (applications, images, libs), **Packages/Versions**, **Files/Paths**, **Licenses**, **Advisories** (from Conseiller), **VEX statements** (from Excitator), **Provenance** (builds, sources), and **Policies** (overlays of determinations) -* **Edges** like `depends_on`, `contains`, `built_from`, `declared_in`, `affected_by`, `vex_exempts`, `governs_with` -* **Time/version** dimension: multiple SBOM snapshots with diffs - -It’s built for investigation and review: find where a vulnerable package enters; see which apps are impacted; understand why a finding exists; simulate a policy version and see the delta. The explorer observes **AOC enforcement**: it never mutates facts; it aggregates and visualizes them. Only the Policy Engine may classify, and classification is displayed as overlays. - ---- - -## 2) Why - -* SBOMs are graphs. Tables flatten what matters and hide transitive risk. -* Engineers, security, and auditors need impact answers quickly: “What pulls in `log4j:2.17` and where is it at runtime?” -* Policy/VEX/advisory interactions are nuanced. A visual overlay makes precedence and outcomes obvious. -* Review is collaborative; you need saved queries, deep links, exports, and consistent evidence. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Domain model - -**Nodes** (typed, versioned, tenant‑scoped): - -* `Artifact`: application, service, container image, library, module -* `Package`: name + ecosystem (purl), `PackageVersion` with resolved version -* `File`: path within artifact or image layer -* `License`: SPDX id -* `Advisory`: normalized advisory id (GHSA, CVE, vendor), source = Conseiller -* `VEX`: statement with product context, status, justification, source = Excitator -* `SBOM`: ingestion unit; includes metadata (tool, sha, build info) -* `PolicyDetermination`: materialized view of Policy Engine results (read‑only overlay) -* `Build`: provenance, commit, workflow run -* `Source`: repo, tag, commit - -**Edges** (directed): - -* `declared_in` (PackageVersion → SBOM) -* `contains` (Artifact → PackageVersion | File) -* `depends_on` (PackageVersion → PackageVersion) with scope attr (prod|dev|test|optional) -* `built_from` (Artifact → Build), `provenance_of` (Build → Source) -* `affected_by` (PackageVersion → Advisory) with range semantics -* `vex_exempts` (Advisory ↔ VEX) scoped by product/component -* `licensed_under` (Artifact|PackageVersion → License) -* `governs_with` (Artifact|PackageVersion → PolicyDetermination) -* `derived_from` (SBOM → SBOM) for superseding snapshots - -**Identity & versioning** - -* Every node has a stable key: `{tenant}:{type}:{natural_id}` (e.g., purl for packages, digest for images). -* SBOM snapshots are immutable; edges carry `valid_from`/`valid_to` for time travel and diffing. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.2 User capabilities (end‑to‑end) - -* **Search & Navigate**: global search (purls, CVEs, repos, licenses), keyboard nav, breadcrumbs, semantic zoom. -* **Lenses**: toggle views (Security, License, Provenance, Runtime vs Dev, Policy effect). -* **Overlays**: - - * **Advisory overlay**: show affected nodes/edges with source, severity, ranges. - * **VEX overlay**: show suppressions/justifications; collapse exempted paths. - * **Policy overlay**: choose a policy version; nodes/edges reflect determinations (severity, status) with explain sampling. -* **Impact analysis**: pick a vulnerable node; highlight upstream/downstream dependents, scope filters, shortest/all paths with constraints. -* **Diff view**: compare SBOM A vs B; show added/removed nodes/edges, changed versions, changed determinations. -* **Saved queries**: visual builder + JSON query; shareable permalinks scoped by tenant and environment. -* **Exports**: GraphML, CSV edge list, NDJSON of findings, PNG/SVG snapshot. -* **Evidence details**: side panel with raw facts, advisory links, VEX statements, policy explain trace, provenance. -* **Accessibility**: tab‑navigable, high‑contrast, screen‑reader labels for nodes and sidebars. - -### 3.3 Query model - -* **Visual builder** for common queries: - - * “Show all paths from Artifact X to Advisory Y up to depth 6.” - * “All runtime dependencies with license = GPL‑3.0.” - * “All artifacts affected by GHSA‑… with no applicable VEX.” - * “Which SBOMs introduced/removed `openssl` between build 120 and 130?” -* **JSON query** (internal, POST body) with: - - * `start`: list of node selectors (type + id or attributes) - * `expand`: edge types and depth, direction, scope filters - * `where`: predicates on node/edge attributes - * `overlay`: policy version id, advisory sources, VEX filters - * `limit`: nodes, edges, timebox, cost budget -* **Cost control**: server estimates cost, denies or pages results; UI streams partial graph tiles. - -### 3.4 UI architecture (Console) - -* **Canvas**: WebGL renderer with level‑of‑detail, edge bundling, and label culling; deterministic layout when possible (seeded). -* **Semantic zoom**: - - * Far: clusters by artifact/repo/ecosystem, color by lens - * Mid: package groups, advisory badges, license swatches - * Near: concrete versions, direct edges, inline badges for policy determinations -* **Panels**: - - * Left: search, filters, lens selector, saved queries - * Right: details, explain trace, evidence tabs (Advisory/VEX/Policy/Provenance) - * Bottom: query expression, diagnostics, performance/stream status -* **Diff mode**: split or overlay, color legend (add/remove/changed), filter by node type. -* **Deep links**: URL encodes query + viewport; shareable respecting RBAC. -* **Keyboard**: space drag, +/- zoom, F to focus, G to expand neighbors, P to show paths. - -### 3.5 Back‑end architecture - -**Graph Indexer (new)** - -* Consumes SBOM ingests, Conseiller advisories, Excitator VEX statements, Policy Engine determinations (read‑only). -* Projects facts into a **property graph** persisted in: - - * Primary: document store + adjacency sets (e.g., Mongo collections + compressed adjacency lists) - * Optional driver for graph DB backends if needed (pluggable) -* Maintains materialized aggregates: degree, critical paths cache, affected artifact counts, license distribution. -* Emits **graph snapshots** per SBOM with lineage to original ingestion. - -**Graph API (new)** - -* Endpoints for search, neighbor expansion, path queries, diffs, overlays, exports. -* Streaming responses for large graphs (chunked NDJSON tiles). -* Cost accounting + quotas per tenant. - -**Workers** - -* **Centrality & clustering** precompute on idle: betweenness approximations, connected components, Louvain clusters. -* **Diff compute** on new SBOM ingestion pairs (previous vs current). -* **Overlay materialization** cache for popular policy versions. - -**Policy Engine integration** - -* Graph API requests can specify a policy version. -* For sampled nodes, the API fetches explain traces; for counts, uses precomputed overlay materializations where available. - -**AOC enforcement** - -* Graph Indexer never merges or edits advisories/VEX; it links them and exposes overlays that the Policy Engine evaluates. -* Conseiller and Excitator remain authoritative sources; severities come from Policy‑governed normalization. - -### 3.6 APIs (representative) - -* `GET /graph/search?q=...&type=package|artifact|advisory|license` -* `POST /graph/query` ⇒ stream tiles `{nodes[], edges[], stats, cursor}` -* `POST /graph/paths` body: `{from, to, depth<=6, constraints{scope, runtime_only}}` -* `POST /graph/diff` body: `{sbom_a, sbom_b, filters}` -* `GET /graph/snapshots/{sbom_id}` ⇒ graph metadata, counts, top advisories -* `POST /graph/export` body: `{format: graphml|csv|ndjson|png|svg, query|snapshot}` -* `GET /graph/saved` / `POST /graph/saved` save and list tenant queries -* `GET /graph/overlays/policy/{version_id}` ⇒ summary stats for caching - -All endpoints tenant‑scoped, RBAC‑checked. Timeouts and pagination by server. Errors return structured diagnostics. - -### 3.7 CLI - -``` -stella sbom graph search "purl:pkg:maven/org.apache.logging.log4j/log4j-core" -stella sbom graph query --file ./query.json --export graphml > graph.graphml -stella sbom graph impacted --advisory GHSA-xxxx --runtime-only --limit 100 -stella sbom graph paths --from artifact:service-a --to advisory:GHSA-xxxx --depth 5 --policy 1.3.0 -stella sbom graph diff --sbom-a 2025-03-15T10:00Z --sbom-b 2025-03-22T10:00Z --export csv > diff.csv -stella sbom graph save --name "openssl-runtime" --file ./query.json -``` - -Exit codes: 0 ok, 2 query validation error, 3 over‑budget, 4 not found, 5 RBAC denied. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -### 3.8 Performance & scale - -* **Progressive loading**: server pages tiles by BFS frontier; client renders incrementally. -* **Viewport culling**: only visible nodes/edges in canvas; offscreen demoted to aggregates. -* **Level‑of‑detail**: simplified glyphs and collapsed clusters at distance. -* **Query budgets**: per‑tenant rate + node/edge caps; interactive paths limited to depth ≤ 6. -* **Caching**: hot queries memoized per tenant + overlay version; diffs precomputed for consecutive SBOMs. - -### 3.9 Security - -* Multi‑tenant isolation at storage and API layers. -* RBAC roles: - - * **Viewer**: browse graphs, saved queries - * **Investigator**: run queries, export data - * **Operator**: configure budgets, purge caches - * **Auditor**: download evidence bundles -* Input validation for query JSON; deny disallowed edge traversals; strict CSP in web app. - -### 3.10 Observability - -* Metrics: tile latency, nodes/edges per tile, cache hit rate, query denials, memory pressure. -* Logs: structured, include query hash, cost, truncation flags. -* Traces: server spans per stage (parse, plan, fetch, overlay, stream). - -### 3.11 Accessibility & UX guarantees - -* Keyboard complete, ARIA roles for graph and panels, high‑contrast theme. -* Deterministic layout on reload for shareable investigations. - -### 3.12 Data retention - -* Graph nodes derived from SBOMs share retention with SBOM artifacts; overlays are ephemeral caches. -* Saved queries retained until deleted; references to missing objects show warnings. - ---- - -## 4) Implementation plan - -### 4.1 Services - -* **Graph Indexer (new microservice)** - - * Subscribes to SBOM ingest events, Conseiller advisory updates, Excitator VEX updates, Policy overlay materializations. - * Builds adjacency lists and node documents; computes aggregates and clusters. - -* **Graph API (new microservice)** - - * Validates and executes queries; streams tiles; composes overlays; serves diffs and exports. - * Integrates with Policy Engine for explain sample retrieval. - -* **SBOM Service (existing)** - - * Emits ingestion events with SBOM ids and lineage; exposes SBOM metadata to Graph API. - -* **Web API Gateway** - - * Routes `/graph/*`, injects tenant context, enforces RBAC. - -### 4.2 Console (Web UI) feature module - -* `packages/features/graph-explorer` - - * Canvas renderer (WebGL), panels, query builder, diff mode, overlays, exports. - * Deep‑link router and viewport state serializer. - -### 4.3 Workers - -* Centrality/clustering worker, diff worker, overlay materialization worker. -* Schedules on low‑traffic windows; backpressure aware. - -### 4.4 Data model (storage) - -* Collections: - - * `graph_nodes`: `{_id, tenant, type, natural_id, attrs, degree, created_at, updated_at}` - * `graph_edges`: `{_id, tenant, from_id, to_id, type, attrs, valid_from, valid_to}` - * `graph_snapshots`: per‑SBOM node/edge references - * `graph_saved_queries`: `{_id, tenant, name, query_json, created_by}` - * `graph_overlays_cache`: keyed by `{tenant, policy_version, hash(query)}` -* Indexes: compound on `{tenant, type, natural_id}`, `{tenant, from_id}`, `{tenant, to_id}`, time bounds. - ---- - -## 5) Documentation changes (create/update) - -1. **`/docs/sbom/graph-explorer-overview.md`** - - * Concepts, node/edge taxonomy, lenses, overlays, roles, limitations. -2. **`/docs/sbom/graph-using-the-console.md`** - - * Walkthroughs: search, navigate, impact, diff, export; screenshots and keyboard cheatsheet. -3. **`/docs/sbom/graph-query-language.md`** - - * JSON schema, examples, constraints, cost/budget rules. -4. **`/docs/sbom/graph-api.md`** - - * REST endpoints, request/response examples, streaming and pagination. -5. **`/docs/sbom/graph-cli.md`** - - * CLI command reference and example pipelines. -6. **`/docs/policy/graph-overlays.md`** - - * How policy versions render in Graph; explain sampling; AOC guardrails. -7. **`/docs/vex/graph-integration.md`** - - * How VEX suppressions appear and how to validate product scoping. -8. **`/docs/advisories/graph-integration.md`** - - * Advisory linkage and severity normalization by policy. -9. **`/docs/architecture/graph-services.md`** - - * Graph Indexer, Graph API, storage choices, failure modes. -10. **`/docs/observability/graph-telemetry.md`** - - * Metrics, logs, tracing, dashboards. -11. **`/docs/runbooks/graph-incidents.md`** - - * Handling runaway queries, cache poisoning, degraded render. -12. **`/docs/security/graph-rbac.md`** - - * Permissions matrix, multi‑tenant boundaries. - -Every doc should end with a “Compliance checklist.” -**Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 6) Tasks - -### 6.1 Backend: Graph Indexer - -* [ ] Define node/edge schemas and attribute dictionaries for each type. -* [ ] Implement event consumers for SBOM ingests, Conseiller updates, Excitator updates. -* [ ] Build ingestion pipeline that populates nodes/edges and maintains `valid_from/valid_to`. -* [ ] Implement aggregate counters and degree metrics. -* [ ] Implement clustering job and persist cluster ids per node. -* [ ] Implement snapshot materialization per SBOM and lineage tracking. -* [ ] Unit tests for each node/edge builder; property‑based tests for identity stability. - -### 6.2 Backend: Graph API - -* [ ] Implement `/graph/search` with prefix and exact match across node types. -* [ ] Implement `/graph/query` with validation, planning, cost estimation, and streaming tile results. -* [ ] Implement `/graph/paths` with constraints and depth limits; shortest path heuristic. -* [ ] Implement `/graph/diff` computing adds/removes/changed versions; stream results. -* [ ] Implement overlays: advisory join, VEX join, policy materialization and explain sampling. -* [ ] Implement exports: GraphML, CSV edge list, NDJSON findings, PNG/SVG snapshots. -* [ ] RBAC middleware integration; multi‑tenant scoping. -* [ ] Load tests with synthetic large SBOMs; define default budgets. - -### 6.3 Policy Engine integration - -* [ ] Add endpoint to fetch explain traces for specific node ids in batch. -* [ ] Add materialization export that Graph API can cache per policy version. - -### 6.4 Console (Web UI) - -* [ ] Create `graph-explorer` module with routes `/graph`, `/graph/diff`, `/graph/q/:id`. -* [ ] Implement WebGL canvas with LOD, culling, edge bundling, deterministic layout seed. -* [ ] Build search, filter, lens, and overlay toolbars. -* [ ] Side panels: details, evidence tabs, explain viewer. -* [ ] Diff mode: split/overlay toggles and color legend. -* [ ] Saved queries: create, update, run; deep links. -* [ ] Export UI: formats, server round‑trip, progress indicators. -* [ ] a11y audit and keyboard‑only flow. - -### 6.5 CLI - -* [ ] Implement `stella sbom graph *` subcommands with JSON IO and piping support. -* [ ] Document examples and stable output schemas for CI consumption. - -### 6.6 Observability & Ops - -* [ ] Dashboards for tile latency, query denials, cache hit rate, memory. -* [ ] Alerting on query error spikes, OOM risk, cache churn. -* [ ] Runbooks in `/docs/runbooks/graph-incidents.md`. - -### 6.7 Docs - -* [ ] Author all docs in section 5, link from Console contextual help. -* [ ] Add end‑to‑end tutorial: “Investigate GHSA‑XXXX across prod artifacts.” - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Acceptance criteria - -* Console renders large SBOM graphs with semantic zoom, overlays, and responsive interactions. -* Users can run impact and path queries with bounded depth and get results within budget. -* VEX suppressions and advisory severities appear correctly and are consistent with policy. -* Diff view clearly shows added/removed/changed nodes/edges between two SBOMs. -* Saved queries and deep links reproduce the same view deterministically (given same data). -* Exports produce valid GraphML/CSV/NDJSON and image snapshots. -* CLI supports search, query, paths, impacted, diff, and export with stable schemas. -* AOC guardrails: explorer never mutates facts; overlays reflect Policy Engine decisions. -* RBAC enforced; all actions logged and observable. - ---- - -## 8) Risks & mitigations - -* **Graph explosion on large monorepos** → tiling, clustering, budgets, and strict depth limits. -* **Inconsistent identities across tools** → canonicalize purls/digests; property‑based tests for identity stability. -* **Policy overlay latency** → precompute materializations for hot policy versions; sample explains only on focus. -* **User confusion** → strong lens defaults, deterministic layouts, legends, in‑context help. - ---- - -## 9) Test plan - -* **Unit**: node/edge builders, identity normalization, cost estimator. -* **Integration**: ingest SBOM + advisories + VEX, verify overlays and counts. -* **E2E**: Playwright flows for search→impact→diff→export; deep link determinism. -* **Performance**: simulate 500k nodes/2M edges; measure tile latency and memory. -* **Security**: RBAC matrix; tenant isolation tests; query validation fuzzing. -* **Determinism**: snapshot round‑trip: same query and seed produce identical layout and stats. - ---- - -## 10) Feature flags - -* `graph.explorer` (UI feature module) -* `graph.paths` (advanced path queries) -* `graph.diff` (SBOM diff mode) -* `graph.overlays.policy` (policy overlay + explain sampling) -* `graph.export` (exports enabled) - -Documented in `/docs/observability/graph-telemetry.md`. - ---- - -## 11) Non‑goals (this epic) - -* Real‑time process/runtime call graphs. -* Full substitution for text reports; Explorer complements Reports. -* Cross‑tenant graphs; all queries are tenant‑scoped. - ---- - -## 12) Philosophy - -* **See the system**: security and license risk are structural. If you cannot see structure, you will miss risk. -* **Evidence over assertion**: every colored node corresponds to raw facts and explainable determinations. -* **Bounded interactivity**: fast, partial answers beat slow “complete” ones. -* **Immutability**: graphs mirror SBOM snapshots and are never rewritten; we add context, not edits. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_6.md b/docs/implplan/EPIC_6.md deleted file mode 100644 index 7de7a5dd..00000000 --- a/docs/implplan/EPIC_6.md +++ /dev/null @@ -1,650 +0,0 @@ -Below is the expanded, “maximum documentation” package for Epic 6. It is paste‑ready for your repo and deliberately formal so engineering, docs, and audit folks can work from the same source of truth. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 6: Vulnerability Explorer (policy‑aware) - -**Short name:** `Vuln Explorer` -**Services touched:** Conseiller (Feedser), Excitator (Vexer), SBOM Service, Policy Engine, Findings Ledger (new), Web API Gateway, Authority (authN/Z), Workers/Scheduler, Telemetry/Analytics, Console (Web UI), CLI -**AOC ground rule:** Conseiller/Excitator aggregate but never merge or rewrite source documents. The Explorer only renders **effective** results as decided by Policy Engine and records human workflow as immutable ledger events. - ---- - -## 1) What it is - -The Vulnerability Explorer is the API and UI for operational triage, investigation, and reporting of vulnerabilities across all artifacts tracked by StellaOps. It correlates SBOM inventory with advisory and VEX evidence, then displays the **effective** status and obligations per the currently selected **Policy version**. It never edits source evidence. It provides: - -* Policy‑aware lists, pivots, and detail views -* Triage workflow with immutable audit ledger -* Risk acceptance with expiry and evidence -* SLA tracking by severity and business tier -* Simulation against other policy versions -* Exports and cryptographically signed “evidence bundles” - -**Identity principle:** one **Finding** per tuple `(artifact_id, purl, version, advisory_key)`, with links to every contributing AdvisoryEvidence and VexEvidence. - ---- - -## 2) Why (concise) - -* Prioritization must reflect **policy and VEX**, not raw feeds. -* Audit requires complete, reproducible lineage: what changed, why, and who decided. -* Operators need consistent APIs, CLI, and a UI that explain determinations, not just list CVEs. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Domain model and contracts - -**Evidence (immutable)** - -* `AdvisoryEvidence` (from Conseiller) - - ```json - { - "id": "adv_evd:...uuid...", - "tenant": "acme", - "source": "ghsa|nvd|vendor|ossindex|... ", - "source_id": "GHSA-xxxx", - "schema": "GHSA|CVE|CSAF-ADV", - "advisory_key": "CVE-2024-12345", - "affected": [{"ecosystem":"npm","purl":"pkg:npm/lodash","ranges":[{"type":"semver","events":[{"introduced":"0.0.0"},{"fixed":"4.17.21"}]}]}], - "cvss": {"version":"3.1","baseScore":7.5,"vectorString":"AV:N/AC:L/..."}, - "severity": "HIGH", - "urls": ["https://..."], - "published": "2024-06-10T12:00:00Z", - "withdrawn": null, - "ingested_at": "2024-06-11T08:43:21Z" - } - ``` -* `VexEvidence` (from Excitator) - - ```json - { - "id": "vex_evd:...uuid...", - "tenant": "acme", - "source": "vendor-csaf", - "schema": "CSAF-VEX", - "advisory_key": "CVE-2024-12345", - "product_scope": [{"purl":"pkg:npm/lodash@4.17.20"}], - "status": "not_affected|affected|fixed|under_investigation", - "justification": "component_not_present|vulnerable_code_not_in_execute_path|... ", - "impact_statement": "Not reachable in Acme Payment Service.", - "timestamp": "2024-06-12T10:00:00Z", - "ingested_at": "2024-06-12T10:10:02Z" - } - ``` -* `InventoryEvidence` (from SBOM Service) - - ```json - { - "id": "inv_evd:...uuid...", - "tenant": "acme", - "artifact_id": "svc:payments@1.14.0", - "sbom_id": "sbom:sha256:...", - "purl": "pkg:npm/lodash@4.17.20", - "scope": "runtime|dev|test", - "runtime_flag": true, - "paths": [["root", "pkg:npm/a", "pkg:npm/lodash"]], - "discovered_at": "2024-06-12T11:00:00Z" - } - ``` - -**PolicyDetermination** (read‑only from Policy Engine) - -```json -{ - "key": { - "artifact_id": "svc:payments@1.14.0", - "purl": "pkg:npm/lodash", - "version": "4.17.20", - "advisory_key": "CVE-2024-12345", - "policy_version": "1.3.0" - }, - "applicable": true, - "effective_severity": "HIGH", - "exploitability": "ACTIVE|LIKELY|UNKNOWN|UNLIKELY", - "signals": {"epss": 0.86, "kev": true, "maturity": "weaponized"}, - "suppression_state": "none|policy|vex", - "obligations": [{"type":"fix_by","due":"2024-07-15"},{"type":"document_risk"}], - "sla": {"due":"2024-07-15","tier":"gold"}, - "rationale": [ - {"rule":"sev.base=nvd","detail":"NVD base:7.5"}, - {"rule":"exploit.upsell.kev","detail":"KEV flag → HIGH"}, - {"rule":"env.weight.prod","detail":"Env=prod no downgrade"} - ] -} -``` - -**Finding identity** - -``` -finding_id = hash(tenant, artifact_id, purl, version, advisory_key) -``` - -**Ledger event** (append‑only, tamper‑evident) - -```json -{ - "event_id": "led:...uuid...", - "finding_id": "f:...hash...", - "tenant": "acme", - "type": "assign|comment|attach|change_state|accept_risk|set_target_fix|verify_fix|reopen", - "payload": {"to":"team:platform","reason":"oncall triage"}, - "actor": {"user_id":"u:42","display":"Dana S."}, - "ts": "2024-06-12T14:01:02Z", - "prev_event_hash": "sha256:...", - "event_hash": "sha256:sha256(canonical_json(event) + prev_event_hash)" -} -``` - -**Projection** (materialized current state for fast lists) - -```json -{ - "finding_id":"f:...hash...", - "tenant":"acme", - "artifact_id":"svc:payments@1.14.0", - "purl":"pkg:npm/lodash", - "version":"4.17.20", - "advisory_key":"CVE-2024-12345", - "effective_severity":"HIGH", - "exploitability":"ACTIVE", - "suppression_state":"none", - "status":"UNDER_INVESTIGATION|REMEDIATING|ACCEPTED|RESOLVED|NEW|SUPPRESSED", - "sla_due":"2024-07-15", - "owner":"team:platform", - "kev":true, - "epss":0.86, - "new_since":"2024-06-12", - "has_fix":true, - "envs":["prod"], - "runtime_flag":true, - "updated_at":"2024-06-12T14:01:02Z" -} -``` - -**Advisory key normalization** - -* Input identifiers: `CVE-*`, `GHSA-*`, vendor IDs. -* Preference order: CVE, then GHSA, else vendor id prefixed with namespace. -* Canonicalization: uppercase, trim, map withdrawn to same key but mark `withdrawn=true` in evidence. -* Conseiller must publish `links: [all source ids]` for provenance. - -### 3.2 Resolver algorithm (candidate findings) - -**Goal:** produce tuples `(artifact_id, purl, version, advisory_key)` where inventory intersects affected ranges and policy deems the path relevant. - -**Pseudocode** - -``` -for each artifact sbom S: - inv = inventory(S) - for each advisory evidence A: - for each affected package spec in A.affected: - for each inv_item in inv where inv_item.purl package == spec.purl package: - if version_in_ranges(inv_item.version, spec.ranges, ecosystem): - if policy.path_scope_allows(inv_item.scope, inv_item.runtime_flag, inv_item.paths): - yield candidate (artifact_id, inv_item.purl, inv_item.version, A.advisory_key) -``` - -**Version semantics per ecosystem** - -* npm: semver, pre-release excluded unless explicitly in range. -* Maven: Maven version rules, handle `-SNAPSHOT`, use maven‑resolver semantics. -* PyPI: PEP 440 versioning. -* Go: semver with `+incompatible` handling. -* OS packages: RPM/DEB epoch:version‑release ordering. - -**Edge cases** - -* Multiple paths: store shortest path and count. -* Dev/test scope: policy may exclude or downgrade. -* Withdrawn advisories: keep as evidence; Policy can set severity to `NONE`. - -### 3.3 VEX precedence and scoping - -* If any matching **VEX** says `not_affected` scoped to the artifact product/component per CSAF product tree, set `suppression_state="vex"` and `applicable=false`. -* If VEX says `fixed` and inventory version is >= fixed version, mark as **Resolved (verified)** after SBOM recrawl confirms. -* If VEX `under_investigation`, no suppression; may add a policy grace period obligation. - -### 3.4 Policy evaluation - -* Inputs: candidate tuple + context (artifact env, business tier, ownership, signals, fix availability). -* Determinations: applicability, effective severity, exploitability, obligations, SLA, suppression. -* Suppression by policy examples: test‑scope only; path through optional deps; package vendored but not linked at runtime. -* Simulation: identical input, alternate `policy_version`; returns determinations without side effects. - -### 3.5 API surface (authoritative) - -**List** - -``` -GET /vuln/findings?policy=1.3.0&sev=high,critical&group_by=artifact&exploit=kev&env=prod&page=1&page_size=100 -``` - -Response - -```json -{ - "page": 1, - "page_size": 100, - "total": 740, - "group_by": "artifact", - "results": [ - {"group":"svc:payments","counts":{"CRITICAL":3,"HIGH":12,"MEDIUM":8},"sla_breaches":2}, - ... - ] -} -``` - -**Query (complex filters)** - -``` -POST /vuln/findings/query -``` - -```json -{ - "policy": "1.3.0", - "filter": { - "severity": [">=MEDIUM"], - "exploit": ["kev", "epss>=0.8"], - "artifact": ["svc:payments", "svc:checkouts"], - "status": ["NEW","UNDER_INVESTIGATION"], - "env": ["prod"] - }, - "sort": [{"field":"effective_severity","dir":"desc"},{"field":"epss","dir":"desc"}], - "page": {"number":1,"size":200} -} -``` - -**Detail** - -``` -GET /vuln/findings/{finding_id}?policy=1.3.0 -``` - -Returns projection, evidence links, policy rationale, paths, history summary. - -**Workflow** - -``` -POST /vuln/findings/{id}/assign { "to": "team:platform" } -POST /vuln/findings/{id}/comment { "text": "triage notes..." } -POST /vuln/findings/{id}/accept-risk { "until":"2025-06-30","reason":"vendor patch pending","evidence":["url|upload_id"] } -POST /vuln/findings/{id}/verify-fix { "sbom_id": "sbom:sha256:..." } -POST /vuln/findings/{id}/target-fix { "version": "4.17.21" } -``` - -**Simulation** - -``` -POST /vuln/simulate -{ - "policy_from": "1.3.0", - "policy_to": "1.4.0", - "query": { "severity":[">=MEDIUM"], "env":["prod"] } -} -``` - -Response includes per‑finding delta `{before, after, diff}`. - -**Export** - -``` -POST /vuln/export { "format":"ndjson","scope":{"query":{...}} } -``` - -Returns a signed bundle (see §3.10). - -**Errors** - -* `400` validation, `403` RBAC, `404` not found, `409` state conflict (idempotency), `429` rate limited, `5xx` server. - -### 3.6 Console (Web UI) - -**Routes** - -* `/vuln` list with saved views -* `/vuln/:id` detail drawer state -* `/vuln/simulate/:policyVersion` diff mode - -**State shape (client)** - -```ts -interface VulnListState { - policyVersion: string; - filters: {...}; - sort: [...]; - columns: string[]; - viewId?: string; - page: {number: number; size: number}; -} -``` - -**UX** - -* Virtualized grid with server paging; column chooser; density toggle. -* Quick filters: severity, exploit signals, status, env, owner, fix availability. -* Detail tabs: Summary, Evidence (raw docs with provenance), Policy (rationale chain), Paths (deep link to Graph Explorer), Fixes, History. -* Simulation bar shows delta chips: `+21 HIGH`, `-9 Suppressed by VEX` etc. -* Evidence bundle dialog previews scope and size. -* a11y: ARIA roles on grid, keyboard shortcuts: `A` assign, `C` comment, `R` accept risk, `V` verify fix. - -### 3.7 CLI - -Commands - -``` -stella vuln list --policy 1.3.0 --sev high,critical --group-by artifact --env prod --json -stella vuln show --id --policy 1.3.0 -stella vuln simulate --from 1.3.0 --to 1.4.0 --sev '>=medium' --delta --json -stella vuln assign --filter 'advisory:CVE-2024-12345 artifact:payments' --to team:platform -stella vuln accept-risk --id --until 2025-06-30 --reason "vendor patch pending" --evidence url:https://ticket/123 -stella vuln verify-fix --id --sbom -``` - -Return codes: `0 ok`, `2 invalid args`, `3 budget exceeded`, `4 not found`, `5 denied`. - -### 3.8 Storage schema (illustrative) - -**Tables** - -```sql --- Evidence -CREATE TABLE evidence_advisory (...); -CREATE INDEX ea_tenant_key ON evidence_advisory(tenant, advisory_key); -CREATE TABLE evidence_vex (...); -CREATE INDEX ev_tenant_key ON evidence_vex(tenant, advisory_key); -CREATE TABLE evidence_inventory (...); -CREATE INDEX ei_artifact_purl ON evidence_inventory(tenant, artifact_id, purl); - --- Ledger -CREATE TABLE findings_ledger_events ( - event_id uuid PRIMARY KEY, - finding_id bytea NOT NULL, - tenant text NOT NULL, - type text NOT NULL, - payload jsonb NOT NULL, - actor jsonb NOT NULL, - ts timestamptz NOT NULL, - prev_event_hash bytea, - event_hash bytea NOT NULL -); -CREATE INDEX fle_find_ts ON findings_ledger_events(tenant, finding_id, ts); - --- Projection -CREATE TABLE findings_projection ( - finding_id bytea PRIMARY KEY, - tenant text NOT NULL, - artifact_id text NOT NULL, - purl text NOT NULL, - version text NOT NULL, - advisory_key text NOT NULL, - policy_version text NOT NULL, - effective_severity text NOT NULL, - exploitability text, - suppression_state text, - status text NOT NULL, - sla_due date, - owner text, - kev boolean, - epss double precision, - envs text[], - runtime_flag boolean, - updated_at timestamptz NOT NULL -); -CREATE INDEX fp_query ON findings_projection(tenant, policy_version, effective_severity, status); -``` - -**Tamper‑evidence** - -* Ledger events use chained SHA‑256 hashes over canonical JSON + previous hash. -* Daily Merkle root of all event hashes is anchored to the audit store (and optionally external timestamping service). - -### 3.9 Performance and scaling - -* P95 list endpoint under 600 ms for 100‑row pages at 5M findings/tenant. -* Projections denormalize heavy joins; background projector uses idempotent jobs keyed by `(tenant,finding_id,policy_version)`. -* Rate limits per tenant and per API key; backpressure on export jobs; exponential retry for projector. - -### 3.10 Evidence bundle format - -* **Container:** ZIP with `manifest.json`, `findings.ndjson`, `advisory_evidence.ndjson`, `vex_evidence.ndjson`, `inventory_evidence.ndjson`, `policy_version.json`, `ledger_events.ndjson`, `CHECKSUMS`. -* **Signing:** Detached signature `bundle.sig` using tenant’s org key (Ed25519). -* **Manifest** - - ```json - {"generated_at":"2024-06-12T15:00:00Z","tenant":"acme","policy_version":"1.3.0","scope":{"query":{...}},"counts":{"findings":421}} - ``` - -### 3.11 Observability - -* Metrics (OpenTelemetry): - - * `vuln_findings_list_latency_ms` (histogram) - * `vuln_projection_lag_seconds` (gauge) - * `vuln_new_findings_total` (counter) - * `vuln_sla_breaches_total` (counter by sev, owner) - * `vuln_simulation_latency_ms` (histogram) -* Logs: structured JSON with `tenant`, `policy_version`, `query_hash`, `result_count`. -* Traces: spans for resolver, policy calls, projection builds, export assembly. -* PII: redact comments in logs; store attachments encrypted at rest (KMS). - -### 3.12 Security & RBAC - -**Roles** - -* Viewer: GET list/detail/export read scope. -* Investigator: Viewer + workflow actions except risk acceptance. -* Operator: Investigator + risk acceptance, verify fix, bulk actions. -* Auditor: Viewer + evidence bundles and ledger integrity checks. - -**ABAC** - -* Attribute constraints: by `artifact.owner`, `env`, and `business_tier`. -* CSRF protection for Console; all POST require anti‑forgery tokens. -* Attachments stored with envelope encryption; signed URLs for limited time access. - -### 3.13 Rollout and migrations - -* Feature flags: `vuln.explorer.ui`, `vuln.explorer.simulation`, `vuln.explorer.bulk_actions`, `vuln.explorer.evidence_bundle`. -* Phase 1: dark launch API and projections. -* Phase 2: UI read‑only list and detail. -* Phase 3: workflow actions and exports. -* Data backfill: replay advisory/VEX/SBOM events to seed projections. -* Compatibility: maintain projection v1 schema for two releases; migration scripts in `/migrations/vuln/`. - ---- - -## 4) Implementation plan - -### 4.1 Services - -* **Findings Ledger (new)** - - * Append‑only event store with projector to `findings_projection`. - * Event validation and canonicalization; hashing and Merkle root anchoring. - -* **Vuln Explorer API (new)** - - * Query/filter engine with policy parameterization and grouping. - * Simulation endpoint. - * Export job orchestrator. - -* **Conseiller / Excitator (updates)** - - * Guarantee canonical `advisory_key` and publish `links[]`. - * No merges; maintain raw payload snapshots. - -* **Policy Engine (updates)** - - * Batch evaluation endpoint `POST /policy/eval/batch` with `simulate` support. - * Return rationale chain with rule IDs. - -* **SBOM Service (updates)** - - * Publish inventory deltas; include `scope`, `runtime_flag`, `paths`. - * Nearest safe version hints. - -* **Workers/Scheduler** - - * Resolver job keyed by `(tenant, artifact_id, sbom_id)`; emits candidate tuples. - * Recompute on policy activation and evidence changes. - -### 4.2 Code structure - -``` -/src/Findings/StellaOps.Findings.Ledger - /api - /projector - /storage -/src/VulnExplorer/StellaOps.VulnExplorer.Api - /routes - /query - /simulation - /export -/packages/console/features/vuln-explorer - /components - /pages - /state -/src/Cli/StellaOps.Cli -``` - -### 4.3 Performance tasks - -* Projection indexes and covering queries; explain plans in `/docs/vuln/perf-notes.md`. -* Cache hot groupings per tenant with TTL and invalidation on ledger projector tick. - ---- - -## 5) Documentation changes (create/update) - -1. `/docs/vuln/explorer-overview.md` - Conceptual model, identities, evidence vs determinations, AOC guarantees. -2. `/docs/vuln/explorer-using-console.md` - Workflows with screenshots, keyboard shortcuts, saved views, deep links. -3. `/docs/vuln/explorer-api.md` - Endpoint specs, query language, grouping, pagination, errors, rate limits. -4. `/docs/vuln/explorer-cli.md` - Commands, flags, examples, exit codes. -5. `/docs/vuln/findings-ledger.md` - Event schema, state machine, hashing, Merkle roots, integrity checks. -6. `/docs/policy/vuln-determinations.md` - Inputs, outputs, precedence rules, simulation semantics. -7. `/docs/vex/explorer-integration.md` - CSAF mapping, scoping to product tree, precedence. -8. `/docs/advisories/explorer-integration.md` - Advisory key normalization, provenance, withdrawn handling. -9. `/docs/sbom/vuln-resolution.md` - Ecosystem version semantics, path sensitivity, scope rules. -10. `/docs/observability/vuln-telemetry.md` - Metrics, logs, traces, dashboards, SLOs. -11. `/docs/security/vuln-rbac.md` - Role mapping, ABAC, attachment encryption, CSRF. -12. `/docs/runbooks/vuln-ops.md` - Recompute storms, projector lag, policy activation drains, export failures. -13. `/docs/install/containers.md` - Add `findings-ledger`, `vuln-explorer-api` images, compose/k8s manifests, resource sizing, health checks. - -> Each doc ends with: **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 6) Engineering tasks - -### Backend: Findings & API - -* [ ] Define evidence and ledger schemas; migrations. -* [ ] Implement resolver for npm, Maven, PyPI, Go, OS packages with property‑based tests for version comparisons. -* [ ] Implement ledger API and projector with idempotency and hashing. -* [ ] Implement list/detail/grouping endpoints with server‑side paging. -* [ ] Implement simulation and export (bundle assembly, signing). -* [ ] Integrate Policy Engine batch eval with rationale traces. -* [ ] RBAC via Authority with ABAC filters. -* [ ] Load tests at 5M findings/tenant; tune indexes. - -### Conseiller/Excitator - -* [ ] Normalize `advisory_key` and persist `links[]`. -* [ ] Ensure raw payload snapshots are retrievable by Explorer for Evidence tab. - -### SBOM Service - -* [ ] Emit `scope`, `runtime_flag`, `paths`; safe version hints. -* [ ] Inventory delta events to trigger resolver. - -### Console - -* [ ] Build grid with virtualization, saved views, deep link serializer. -* [ ] Implement detail tabs and path deep‑links to Graph Explorer. -* [ ] Add simulation bar and delta chips. -* [ ] Evidence bundle dialog. -* [ ] a11y keyboard flow and ARIA labeling; unit and E2E tests. - -### CLI - -* [ ] `stella vuln list|show|simulate|assign|accept-risk|verify-fix` with `--json` and CSV export. -* [ ] Stable output schemas; pipe‑friendly defaults. - -### Observability/Ops - -* [ ] Dashboards for list latency, projection lag, new/reopened, SLA breaches. -* [ ] Alerts on projector backlog, API 5xx spikes, export failures. -* [ ] Runbooks in `/docs/runbooks/vuln-ops.md`. - -### Docs - -* [ ] Author files listed in §5 with cross‑links to Policy Studio and SBOM Graph Explorer. -* [ ] Update `/docs/install/containers.md` with new images and compose/k8s snippets. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Acceptance criteria - -* List and detail views reflect **effective** policy outcomes and update instantly when switching policy versions. -* Evidence tab shows all raw advisory/VEX documents with provenance; no source merging. -* Resolver respects ecosystem semantics, scope, and paths; path tab round‑trips to Graph Explorer. -* Ledger events are immutable and reconstruct historical list states accurately. -* Simulation returns diffs without side effects and matches Policy Engine outputs. -* CLI/API support paging, grouping, export, simulation; contracts stable and documented. -* RBAC and tenant isolation validated by tests; attachments encrypted. -* P95 performance budgets met; dashboards green for SLOs. - ---- - -## 8) Risks and mitigations - -* **Advisory identity collisions** → strict canonicalization; preserve `links[]`; never merge raw docs. -* **Projection lag** → backpressure, worker autoscaling, health checks; alerting on lag. -* **Resolver false positives** → path evidence required; dev/test scope rules explicit; ecosystem‑specific tests. -* **User confusion over suppression** → explicit badges; Policy tab with rationale and “why changed.” -* **Export size** → NDJSON streaming, size estimator in UI, scope previews. - ---- - -## 9) Test plan - -* **Unit:** version comparators, resolver per ecosystem, policy mapping, ledger state machine. -* **Integration:** SBOM + advisories + VEX ingestion, candidate generation, policy application, suppression precedence. -* **E2E Console:** triage, bulk assign, simulation, evidence bundle download; keyboard‑only flow. -* **Performance:** list/grouping at target scale; projector rebuild; export assembly. -* **Security:** RBAC matrix, ABAC filters, CSRF, signed URL lifetimes, tamper‑evidence verification. -* **Determinism:** time‑travel snapshots reproduce prior states byte‑for‑byte. - ---- - -## 10) Philosophy - -* **Facts first, decisions second.** Evidence is immutable; decisions and workflow sit on top in a ledger. -* **Policy is the lens.** The same facts can imply different obligations; the system must make that explicit and reproducible. -* **Audit > convenience.** Every state change is justified, signed, and verifiable. -* **No hidden magic.** If anything is suppressed, the UI shows the rule or VEX that did it, with documents attached. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_7.md b/docs/implplan/EPIC_7.md deleted file mode 100644 index 6208ecd5..00000000 --- a/docs/implplan/EPIC_7.md +++ /dev/null @@ -1,545 +0,0 @@ -Below is the expanded, “maximum documentation” package for Epic 7. It is paste‑ready for your repo and deliberately formal so engineering, docs, governance, and audit can work from the same source of truth. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 7: VEX Consensus Lens - -**Short name:** `VEX Lens` -**Services touched:** Excitator (Vexer), Conseiller (Feedser), SBOM Service, Policy Engine, Findings Ledger, Web API Gateway, Authority (authN/Z), Console (Web UI), CLI, Telemetry/Analytics -**AOC ground rule:** Excitator and Conseiller aggregate but never merge or rewrite source documents. The Lens only computes a **derived, reproducible** consensus view while preserving all raw evidence and provenance. - ---- - -## 1) What it is - -The VEX Consensus Lens is a deterministic computation and presentation layer that ingests all available VEX statements about a given advisory key (e.g., CVE) and product/context, then produces an **explicit consensus state** for each `(artifact_id, purl, version, advisory_key)` tuple. It answers: “Given multiple, possibly conflicting VEX statements from different issuers, what is the most trustworthy, policy‑consistent interpretation for this artifact and version?” - -It never edits or merges VEX documents. It normalizes them, aligns their **product scope** to SBOM inventory, scores issuers via a tenant‑configurable **trust model**, applies time and version scoping, and outputs: - -* `consensus_state`: `NOT_AFFECTED | AFFECTED | FIXED | UNDER_INVESTIGATION | INCONCLUSIVE | DISPUTED` -* `confidence`: 0.0–1.0 numeric score -* `rationale`: structured explanation of evidence, weights, and rules applied -* `quorum`: weighted vote breakdown by issuer, timestamp, justification, and version applicability - -The Lens plugs into the Policy Engine. Policy remains the source of truth for applicability, severity, and obligations; the Lens supplies structured signals and provenance that policy can use to suppress findings, downgrade risk, or set SLAs. - -Key properties: - -* **Reproducible:** Same inputs and policy yield same outputs. -* **Explainable:** Every output carries a machine‑readable rationale chain. -* **Scoped:** Product trees and version ranges are resolved against actual SBOM inventory. -* **Immutable evidence:** All raw VEX docs remain intact, retrievable, and linkable. - ---- - -## 2) Why (concise) - -Real ecosystems have overlapping VEX statements from upstream maintainers, vendors, distros, and third parties. Operators need a single, defensible view without losing provenance. The Lens reduces noise, flags conflicts, and turns fragmented VEX evidence into auditable signals that policy and humans can act on. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Input model - -**From Excitator (Vexer):** - -* Raw `VexEvidence` documents (CSAF VEX, OpenVEX, CycloneDX VEX) with: - - * `advisory_key` (canonicalized) - * product tree or component coordinates (purl, CPE, vendor IDs) - * status (`not_affected`, `affected`, `fixed`, `under_investigation`) - * justifications (CSAF, OpenVEX enumerations) - * version ranges or fixed versions if available - * timestamps (issued, last_updated), source URLs - * cryptographic metadata (signature, issuer, certificate chain) if present - -**From SBOM Service:** - -* Inventory for each artifact: purls, versions, dependency paths, scopes, env flags. - -**From Issuer Directory (new)** - -* Directory of known VEX issuers: - - * identity, organization, domain, CSAF publisher metadata - * public keys and trust anchors (Ed25519/X.509/PKIX/PKCS7/DSSE) - * default trust weight - * tenancy‑specific overrides - -**From Policy Engine:** - -* Policy version and options relevant to VEX evaluation: - - * trust model parameters - * confidence thresholds per environment/tier - * justification whitelist/blacklist - * recency requirements and expiry windows - * precedence rules for status conflicts - -### 3.2 Normalization - -1. **Canonical advisory key:** CVE preferred; GHSA mapped; vendor IDs namespaced. -2. **Status mapping:** Normalize all encodings to `NOT_AFFECTED | AFFECTED | FIXED | UNDER_INVESTIGATION`. -3. **Product scope alignment:** Convert CSAF product tree/CPE to purl variants using deterministic mappings; store mapping evidence. -4. **Version scoping:** For each evidence, compute `applies_to(version)` using ecosystem comparators (npm semver, Maven, PEP 440, Go semver, RPM/DEB EVR). -5. **Signature verification:** If signed, verify against Issuer Directory trust anchors; attach `sig_verified=true/false` and chain metadata. -6. **Temporal fields:** Compute `effective_at` (issued), `observed_at` (ingested), and staleness. - -### 3.3 Trust model - -Each `VexEvidence` gets a base weight `w_base` from issuer type and verification: - -* Maintainer/Upstream signed: 0.9 -* Maintainer/Upstream unsigned: 0.7 -* Distro/SIG signed: 0.8 -* Vendor of downstream product signed: 0.8 -* Third‑party scanner VEX: 0.4 -* Unknown/unsigned with weak provenance: 0.2 - -Weights are then adjusted: - -``` -w = w_base - * f_signature(sig_verified) // e.g., 1.1 if verified, 0.8 if unverifiable - * f_recency(age_days) // decay after T days (policy) - * f_justification(type) // e.g., "component_not_present" lower if SBOM shows present - * f_scope_match(score) // quality of product match: exact purl > family > CPE wildcard - * f_env(app_env) // optional env-specific multipliers -``` - -All `f_*` are bounded to [0.5, 1.2] by default to prevent runaway effects. Tenants can override per Policy Studio. - -### 3.4 Consensus algorithm - -For a tuple `(artifact_id, purl, version, advisory_key)`: - -1. **Collect** all normalized `VexEvidence` whose product scope maps to `purl` and `applies_to(version)==true`. - -2. **Bucket** by normalized status; compute `W(status) = Σ w(evidence)` per status. - -3. **Apply precedence** rules from policy: - - * If `W(NOT_AFFECTED)` exceeds threshold `T_na` and there is no `FIXED` evidence contradictory for the same version, propose `NOT_AFFECTED`. - * If any `FIXED` applies and inventory version ≥ fixed version, propose `FIXED`. - * If `W(AFFECTED)` ≥ `T_aff` and no dominating `NOT_AFFECTED`, propose `AFFECTED`. - * If `W(UNDER_INVESTIGATION)` dominates and others below thresholds, propose `UNDER_INVESTIGATION`. - * If both `AFFECTED` and `NOT_AFFECTED` exceed thresholds within a small margin `δ`, mark `DISPUTED`. - * Otherwise `INCONCLUSIVE`. - -4. **Confidence score:** - - ``` - confidence = W(winning_status) / (W(AFFECTED)+W(NOT_AFFECTED)+W(FIXED)+W(UNDER_INVESTIGATION) + ε) - ``` - - Clip to [0.0, 1.0]. - -5. **Rationale chain:** - - * Winning status, thresholds used, top 5 contributing evidences with weights and reasons, product mapping quality, version scoping evidence, and policy knobs that influenced the result. - -6. **Quorum summary:** - - * List issuers and their votes, signature state, timestamps, and justifications. - -### 3.5 Policy interaction - -* The Lens returns `consensus_state`, `confidence`, and structured `signals`. -* Policy Engine consumes these and may: - - * Suppress findings automatically on `NOT_AFFECTED` confidence ≥ `P_na`. - * Downgrade severity or extend SLA when `UNDER_INVESTIGATION` from high‑trust issuers. - * Require human approval when `DISPUTED`. - * Treat `FIXED` as resolved only when SBOM crawl verifies the fixed version or a `verify_fix` ledger event exists. - -**Simulation:** Policy Studio can simulate different trust weights and thresholds and see consensus deltas without side effects. - -### 3.6 Data contracts - -**ConsensusRecord (materialized)** - -```json -{ - "id": "cons:sha256(tenant|artifact|purl|version|advisory|policy)", - "tenant": "acme", - "artifact_id": "svc:payments@1.14.0", - "purl": "pkg:npm/lodash@4.17.20", - "advisory_key": "CVE-2024-12345", - "policy_version": "1.3.0", - "consensus_state": "NOT_AFFECTED", - "confidence": 0.87, - "weights": {"AFFECTED":0.31,"NOT_AFFECTED":1.25,"FIXED":0.00,"UNDER_INVESTIGATION":0.12}, - "top_evidence": ["vex_evd:...","vex_evd:..."], - "quorum": [ - {"issuer":"lodash-maintainers","status":"NOT_AFFECTED","w":0.9,"sig_verified":true,"just":"vulnerable_code_not_present","issued":"2024-06-08"}, - {"issuer":"vendorX-distro","status":"AFFECTED","w":0.25,"sig_verified":false,"just":"generic_advisory","issued":"2024-06-07"} - ], - "rationale": [ - {"rule":"trust.weight.issuer","detail":"maintainer signed evidence 0.9"}, - {"rule":"scope.match.exact","detail":"exact purl match"}, - {"rule":"justification.vcnp","detail":"supported by SBOM callgraph hint"} - ], - "updated_at": "2024-06-12T10:00:00Z" -} -``` - -**Issuer Directory entry** - -```json -{ - "issuer_id": "iss:lodash", - "org": "Lodash Maintainers", - "domains": ["lodash.com"], - "keys": [{"type":"ed25519","pub":"...","expires":"2026-12-31"}], - "default_weight": 0.9, - "metadata": {"csaf_publisher": true} -} -``` - -### 3.7 APIs - -**Compute/Query** - -``` -GET /vex/consensus?artifact=svc:payments@1.14.0&purl=pkg:npm/lodash@4.17.20&advisory=CVE-2024-12345&policy=1.3.0 -POST /vex/consensus/query { "policy":"1.3.0", "filter": { "state":["DISPUTED","INCONCLUSIVE"], "confidence":"<0.6", "env":["prod"] }, "page":{...} } -GET /vex/consensus/{id} // full record -POST /vex/consensus/simulate // override trust knobs and thresholds for what-if -``` - -**Issuer Directory** - -``` -GET /vex/issuers -POST /vex/issuers (admin) -POST /vex/issuers/{id}/keys (admin) -``` - -**Exports** - -``` -POST /vex/consensus/export { "format":"ndjson","scope":{"filter":{...}} } -``` - -**Errors** - -* `400` invalid mapping, `403` RBAC, `404` not found, `409` conflict, `429` rate limit. - -### 3.8 Console (Web UI) - -Routes: - -* `/vex/consensus` overview with filters: state, confidence, issuer, advisory, artifact, env. -* `/vex/consensus/:id` detail: Evidence pane, Quorum graph, Policy impact, SBOM path links. - -UX elements: - -* **Quorum bar:** stacked bar showing weights per status; hover reveals issuer contributions. -* **Confidence chip:** numeric and qualitative band (Low/Med/High). -* **Evidence table:** paged list of VEX docs with signature icon, scope match quality tag, justification tag, issued/updated timestamps. -* **Conflict view:** for `DISPUTED`, show side-by-side issuer rationales and suggested next steps. -* **Deep link** into Vulnerability Explorer detail, preselecting the Policy version used for the consensus. - -A11y: - -* ARIA roles on grid and bars; keyboard shortcuts `S` switch policy, `T` trust presets, `E` export. - -### 3.9 CLI - -Commands: - -``` -stella vex consensus list --policy 1.3.0 --state disputed,inconclusive --confidence '<0.6' --artifact payments --json -stella vex consensus show --id --policy 1.3.0 -stella vex simulate --policy 1.3.0 --trust 'issuer:lodash=1.0,issuer:vendorX=0.5' --thresholds 'na=1.0,aff=0.6' --json -stella vex issuers list -stella vex export --filter 'artifact:payments advisory:CVE-2024-12345' --out vex-consensus.ndjson -``` - -Exit codes: `0` ok, `2` invalid args, `4` not found, `5` denied. - -### 3.10 Storage schema (illustrative) - -```sql --- Normalized VEX (reference Excitator id; do not alter raw) -CREATE TABLE vex_normalized ( - id uuid PRIMARY KEY, - tenant text NOT NULL, - evidence_id text NOT NULL, -- link to Excitator - advisory_key text NOT NULL, - issuer_id text, - status text NOT NULL, -- NOT_AFFECTED|AFFECTED|FIXED|UNDER_INVESTIGATION - justification text, - purl text, -- normalized mapping target - version_range jsonb, -- ecosystem-specific encoding - sig_verified boolean, - scope_score real, -- 0..1 quality of mapping - issued timestamptz, - updated timestamptz, - w_base real, - UNIQUE (tenant, evidence_id) -); - --- Issuer Directory -CREATE TABLE vex_issuers ( - issuer_id text PRIMARY KEY, - tenant text NOT NULL, - org text NOT NULL, - default_weight real NOT NULL, - metadata jsonb, - UNIQUE(tenant, org) -); - -CREATE TABLE vex_issuer_keys ( - id uuid PRIMARY KEY, - issuer_id text NOT NULL REFERENCES vex_issuers(issuer_id), - key_type text NOT NULL, - pubkey text NOT NULL, - expires timestamptz -); - --- Consensus projection -CREATE TABLE vex_consensus ( - id bytea PRIMARY KEY, - tenant text NOT NULL, - artifact_id text NOT NULL, - purl text NOT NULL, - version text NOT NULL, - advisory_key text NOT NULL, - policy_version text NOT NULL, - consensus_state text NOT NULL, - confidence real NOT NULL, - weights jsonb NOT NULL, - top_evidence text[] NOT NULL, - updated_at timestamptz NOT NULL -); - -CREATE INDEX vc_query ON vex_consensus(tenant, policy_version, consensus_state, confidence); -``` - -### 3.11 Integration with Findings Ledger and Vuln Explorer - -* The Vuln Explorer reads `vex_consensus` for each finding and renders: - - * Consensus chip, confidence, and a link to full quorum. - * For `NOT_AFFECTED` with confidence ≥ policy threshold, show “Suppressed by VEX (Consensus)” badge. - * For `DISPUTED`, open a triage banner prompting manual review and optional ledger comment/assignment. - -* Ledger receives no new event type from lens computation itself. Human actions triggered by lens views produce standard events (`comment`, `assign`, `change_state`). - -### 3.12 Security & RBAC - -Roles: - -* Viewer: query consensus read‑only. -* Investigator: Viewer + export. -* Operator: Investigator + trust simulation. -* Admin: manage Issuer Directory entries and keys. - -CSRF for Console; ABAC scoping by artifact ownership and environment. - -### 3.13 Observability - -Metrics: - -* `vex_consensus_compute_latency_ms` (histogram) -* `vex_consensus_records_total` (counter) -* `vex_consensus_disputed_total` (counter by issuer combinations) -* `vex_consensus_staleness_seconds` (gauge) -* `vex_signature_verification_rate` (gauge) - -Logs: structured events with `tenant`, `policy_version`, `advisory_key`, `quorum_summary`. -Traces: spans for normalization, mapping, trust weighting, consensus decision, DB writes. - -### 3.14 Performance & scaling - -Targets: - -* P95 query under 500 ms for 100‑row pages at 10M consensus records/tenant. -* Projection jobs are idempotent and keyed by `(tenant, artifact, purl, version, advisory, policy)`; backpressure with work queues. -* Cache popular queries with tenant‑scoped TTL; invalidate on Excitator or policy changes. - -### 3.15 Edge cases - -* **Ambiguous product mapping:** mark low `scope_score`, cap weight, surface warning in UI. -* **VEX “not present” vs SBOM shows present:** down‑weight with `f_justification`, require manual check. -* **Withdrawn or superseded VEX:** decay to near zero; keep provenance. -* **Partial fixes:** if fixed version applies to subset of platforms, map to env or arch dimension when available. -* **Time travel:** consensus recalculated as of a timestamp using only evidence ≤ `as_of` and the corresponding policy version. - ---- - -## 4) Implementation plan - -### 4.1 Services - -* **VEX Lens Service (new)** - - * Normalization pipeline, trust weighting, consensus computation, and projections. - * Batch recompute on policy activation and Excitator deltas. - -* **Excitator (updates)** - - * Ensure all VEX evidence carries issuer hints and raw signature blobs when present. - * Publish product trees and original coordinates intact. - -* **Policy Engine (updates)** - - * Add VEX trust knobs, thresholds, recency decay, and status precedence. - * Batch eval endpoint accepts `consensus inputs` where needed. - -* **Issuer Directory (new)** - - * Manage issuer metadata and keys; tenant overrides; audit logs. - -### 4.2 Code structure - -``` -/src/VexLens/StellaOps.VexLens - /normalizer - /mapping # CPE/purl translators - /trust # weighting functions - /consensus # algorithm and projections - /api -/src/Excititor # updates -/src/Policy/__Libraries/StellaOps.Policy # updates -/src/IssuerDirectory/StellaOps.IssuerDirectory -/packages/console/features/vex-consensus -/src/Cli/StellaOps.Cli -``` - -### 4.3 Rollout - -* Phase 1: API read‑only with basic trust model, Console list/detail, no simulation. -* Phase 2: Policy Studio integrations and simulation. -* Phase 3: Issuer Directory admin flows, exports, and advanced mapping diagnostics. - ---- - -## 5) Documentation changes (create/update) - -1. `/docs/vex/consensus-overview.md` - Purpose, scope, terminology, evidence vs derived view, AOC guarantees. - -2. `/docs/vex/consensus-algorithm.md` - Normalization, mapping, weighting, thresholds, precedence, formulas, examples. - -3. `/docs/vex/issuer-directory.md` - Managing issuers, keys, trust overrides, security model. - -4. `/docs/vex/consensus-api.md` - Endpoints, request/response schemas, errors, pagination, rate limits. - -5. `/docs/vex/consensus-console.md` - Screens, filters, conflict workflows, a11y, deep links. - -6. `/docs/policy/vex-trust-model.md` - Policy knobs, thresholds, decay, simulation. - -7. `/docs/sbom/vex-mapping.md` - Product tree mapping to purl/version, ecosystem comparators, edge cases. - -8. `/docs/security/vex-signatures.md` - Signature verification flows, key management, auditing. - -9. `/docs/runbooks/vex-ops.md` - Recompute storms, mapping failures, signature errors, lag, quotas. - -All docs end with the imposed rule statement. - ---- - -## 6) Engineering tasks - -### Backend core - -* [ ] Implement normalization for CSAF VEX, OpenVEX, CycloneDX VEX. -* [ ] Build product mapping library (CPE→purl, vendor tokens→purl families). -* [ ] Implement signature verification (Ed25519/PKIX/DSSE) using Issuer Directory keys. -* [ ] Implement trust weighting functions and configurable parameters. -* [ ] Implement consensus algorithm with unit tests and property tests. -* [ ] Materialize `vex_consensus` projection with indexes and idempotent workers. -* [ ] Batch recompute on policy activation and Excitator deltas. - -### APIs & Integrations - -* [ ] `/vex/consensus` query, detail, simulate, export. -* [ ] Policy Engine: consume consensus signals; add thresholds and precedence. -* [ ] Vuln Explorer: show consensus chip and triage banners; deep link to Lens. - -### Issuer Directory - -* [ ] CRUD for issuers and keys, audit logs, RBAC. -* [ ] Import common CSAF publishers; seed with sane defaults. - -### Console - -* [ ] Build list grid with filters and saved views. -* [ ] Quorum bar and Evidence table with signature icons and scope quality tags. -* [ ] Conflict view for `DISPUTED`. -* [ ] Simulation drawer integrated with Policy Studio. - -### CLI - -* [ ] `stella vex consensus list|show|simulate|export` with JSON/CSV. -* [ ] Stable schemas; tests for piping and scripting. - -### Observability/Perf - -* [ ] Metrics, logs, traces as specified; dashboards. -* [ ] Load tests at 10M consensus records/tenant; optimize indexes and caches. - -### Docs - -* [ ] Author and cross‑link all docs listed in §5. -* [ ] Add examples and screenshots to Console doc. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Acceptance criteria - -* Normalization supports CSAF VEX, OpenVEX, CycloneDX VEX with product tree mapping to purls across npm, Maven, PyPI, Go, RPM/DEB. -* Signature verification works and affects weights; unverifiable signatures do not crash flows. -* Consensus outputs are reproducible, explainable, and queryable at scale. -* Vuln Explorer displays consensus state and affects policy outcomes per thresholds. -* Simulation reflects policy trust changes without side effects and returns rationale deltas. -* CLI/API feature parity; evidence and quorum are exportable. -* P95 performance budgets met; dashboards reflect health. - ---- - -## 8) Risks and mitigations - -* **Mapping errors (CPE→purl):** use conservative scope scores, cap weights, surface warnings, manual override hooks in Policy Studio. -* **Malicious or mistaken issuer:** signature verification plus trust weighting and tenancy overrides. -* **Evidence storms:** debounce recompute; batch and shard workers; backpressure and prioritization. -* **User confusion with conflicting VEX:** clear conflict UI, rationale chains, suggested actions, and policy banners. -* **Stale statements:** recency decay and expiry windows in policy. - ---- - -## 9) Test plan - -* **Unit:** status mapping, comparators per ecosystem, trust weighting, threshold math. -* **Property tests:** invariants such as monotonicity with added supporting evidence and idempotent recompute. -* **Integration:** Excitator→Lens→Policy→Vuln Explorer pipeline with signed/unsigned, conflicting, and stale evidence. -* **E2E Console:** list filters, detail with quorum, conflict workflows, export, simulation. -* **Security:** RBAC on Issuer Directory, CSRF for Console, signature verification path traversal guards. -* **Performance:** cold/hot query latencies, recompute throughput, cache hit ratios. -* **Determinism:** time‑travel snapshots reproduce prior consensus states. - ---- - -## 10) Philosophy - -* **Consensus, not replacement.** The Lens summarizes without erasing dissent. -* **Trust is contextual.** Tenants must tune weights and thresholds to their environments. -* **Proof over prose.** Every decision comes with math, provenance, and a rationale chain. -* **Safety by design.** When in doubt, surface conflicts instead of silently suppressing. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_8.md b/docs/implplan/EPIC_8.md deleted file mode 100644 index babe78f5..00000000 --- a/docs/implplan/EPIC_8.md +++ /dev/null @@ -1,440 +0,0 @@ -Below is the “maximum documentation” bundle for Epic 8. It’s engineered to be pasted into your repo without turning into yet another unread wiki tomb. Slight sarcasm included to keep blood flowing. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 8: Advisory AI Assistant (summaries, conflict explain, remediation hints) - -**Short name:** `Advisory AI` -**Services touched:** Conseiller (Feedser), Excitator (Vexer), VEX Lens, SBOM Service, Policy Engine, Findings Ledger, Web API Gateway, Authority (authN/Z), Console (Web UI), CLI, Telemetry/Analytics -**AOC ground rule:** Conseiller and Excitator aggregate but never merge or mutate source docs. Advisory AI produces derived summaries and plans with strict provenance and citations. No silent rewriting of evidence. Ever. - ---- - -## 1) What it is - -Advisory AI is a tenant‑scoped, retrieval‑augmented assistant that turns noisy security advisories and VEX statements into three consumable artifacts: - -1. **Advisory Summary** - Condenses one or more advisories (CSAF, OSV, GHSA, vendor PDFs, distro notices) into a concise brief with key facts: affected ranges, exploit status, impact, known workarounds, fixed versions, and links. Always cites the exact sources and sections used. - -2. **Conflict Explain** - Explains why VEX statements or advisories disagree for a specific artifact and version. Uses the VEX Consensus Lens outputs and issuer trust model to produce a human‑readable, step‑by‑step explanation: who said what, where the product scoping diverges, and what policy thresholds caused the final state. - -3. **Remediation Hints** - Suggests practical next steps: upgrade paths compatible with your dependency graph, backports, config toggles, temporary policy suppressions, or compensating controls. Every hint is grounded in SBOM, environment, and policy. It ships as structured JSON plus a human summary, ready to paste into a ticket. - -It lives in the Console as a side panel, in the CLI for batch runs, and via APIs for automation. It does not change scanner results or consensus on its own. Humans remain in charge. The machine does the skimming and the math so humans can keep the judgment and the coffee. - ---- - -## 2) Why (brief) - -Advisories are long, inconsistent, and sometimes contradictory. Teams waste cycles reconciling PDFs with package manifests. The assistant eliminates that sludge: fast summaries, explicit conflict explanations, and remediation hints that are actually applicable to your software, not to an imaginary ideal project from 2013. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Capabilities - -* **Summaries** - - * Input: one advisory or a bundle linked by the same advisory key (CVE, GHSA, vendor‑ID), product scope, and environment. - * Output: - - * 150 to 300 words summary - * `AdvisorySummary JSON` (schema below) - * Citations with paragraph anchors - * Confidence label and coverage score (how much of the advisory set is represented) -* **Conflict Explain** - - * Input: `(artifact_id, purl, version, advisory_key)` tuple. - * Output: narrative plus a structured breakdown of consensus math, issuer votes, product mapping mismatches, and the exact policy knobs that tipped the result. -* **Remediation Hints** - - * Input: same tuple plus SBOM context and environment. - * Output: ranked list of remediation options with feasibility score, blast radius estimate (derived from dependency paths), effort class, and links to fixed versions. Includes “do nothing” when the VEX consensus is not affected. - -### 3.2 System design - -**Architecture diagram in words (because ASCII art is a crime):** - -1. **Retrievers** - - * Structured retriever over Conseiller’s normalized advisory fields. - * Vector retriever over advisory text chunks with paragraph anchors. - * VEX retriever over Excitator evidence and VEX Lens consensus. - * SBOM retriever for purl, version, dependency paths, env flags. -2. **Deterministic resolvers** - - * Version comparators per ecosystem. - * Range satisfaction checks. - * Dependency path scorers and blast radius estimator. -3. **Orchestrator** - - * Task‑specific prompt templates for Summary, Conflict, Remediation. - * Tool calls to deterministics (version check, graph crawl) with results injected into the prompt as structured context. - * Strict token budgets and truncation rules to avoid model babble. -4. **Models** - - * Default: on‑prem inference container with mid‑sized model. - * Optional: tenant‑enabled remote inference. Disabled by default. - * Temperature locked low for summary and conflict. Slightly higher for remediation narrative phrasing. No creativity in facts. -5. **Guardrails** - - * Prompt injection defense by stripping or quarantining advisory text that tries to instruct the model. - * Fact boundary tagger. The assistant must only state facts that appear in structured inputs or cited chunks. - * Redaction of secrets before prompts. - * Output validator checks: required JSON fields, numeric ranges, valid version strings. - -### 3.3 Data contracts - -**AdvisorySummary JSON** - -```json -{ - "advisory_key": "CVE-2025-12345", - "sources": [ - {"id":"csaf:vendorA:2025-001","uri":"...","sections":["2.1","3.4"]}, - {"id":"osv:pkg:npm/lodash","uri":"...","sections":["affected","references"]} - ], - "affected_ranges": [ - {"ecosystem":"npm","purl_family":"pkg:npm/lodash","introduced":"<4.17.15","fixed": "4.17.21"} - ], - "exploit_status": "no_known_exploit | poc_public | exploited_in_the_wild | n/a", - "impact": {"cvss":[{"vector":"CVSS:3.1/AV:N/...","score":7.5}], "cwes":["CWE-79"]}, - "workarounds": ["Disable feature X", "Set flag Y=false"], - "fixed_versions": ["4.17.21"], - "notes": "Vendor states not affected on platform Z due to build option W.", - "coverage_score": 0.86, - "generated_at": "2025-10-25T12:00:00Z" -} -``` - -**ConflictExplanation JSON** - -```json -{ - "tuple": {"artifact_id":"svc:checkout@1.9.0","purl":"pkg:npm/lodash@4.17.20","advisory_key":"CVE-2025-12345"}, - "consensus": {"state":"NOT_AFFECTED","confidence":0.82}, - "quorum": [ - {"issuer":"lodash-maintainers","status":"NOT_AFFECTED","weight":0.9,"sig":true,"justification":"component_not_present"}, - {"issuer":"vendorX-distro","status":"AFFECTED","weight":0.25,"sig":false,"justification":"generic"} - ], - "policy_factors": {"na_threshold":1.0,"aff_threshold":0.6,"recency_decay_days":90}, - "mapping_issues": [{"kind":"cpe_to_purl","score":0.6,"detail":"CPE wildcard matched multiple purls"}], - "explanation_steps": [ - "Exact purl match found for maintainer VEX; weight 0.9", - "Distro advisory generic; scope score 0.5; effective weight 0.25", - "NA threshold met. Result set to NOT_AFFECTED" - ] -} -``` - -**RemediationPlan JSON** - -```json -{ - "tuple": {"artifact_id":"svc:checkout@1.9.0","purl":"pkg:npm/lodash@4.17.20","advisory_key":"CVE-2025-12345"}, - "options": [ - { - "kind": "upgrade", - "target_version": "4.17.21", - "feasibility": 0.92, - "blast_radius": {"direct_callers":3,"transitive_depth":2}, - "effort": "low | medium | high", - "rationale": "Semver patch, no breaking APIs in release notes", - "links": ["release_notes_uri"] - }, - { - "kind": "workaround", - "action": "Set SAFE_MODE=true", - "feasibility": 0.6, - "blast_radius": {"feature_flags":["SAFE_MODE"]}, - "effort": "low", - "rationale": "Vendor states mitigation reduces attack surface on feature X" - } - ], - "preferred": 0, - "policy_effects": {"sla_days": 7, "severity_override": "medium_if_not_fixed"}, - "generated_at": "2025-10-25T12:00:00Z" -} -``` - -### 3.4 APIs - -``` -POST /advisory/ai/summary -{ - "advisory_key":"CVE-2025-12345", - "artifact_id":"svc:checkout@1.9.0", - "purl":"pkg:npm/lodash@4.17.20", - "sources":["csaf:*","osv:*"], // optional filters - "policy_version":"1.3.0", - "lang":"en" -} --> 200 { "summary_text":"...", "summary": {AdvisorySummary}, "citations":[...] } - -POST /advisory/ai/conflict -{ - "artifact_id":"svc:checkout@1.9.0", - "purl":"pkg:npm/lodash@4.17.20", - "advisory_key":"CVE-2025-12345", - "policy_version":"1.3.0" -} --> 200 { "explanation_text":"...", "explanation": {ConflictExplanation} } - -POST /advisory/ai/remediation -{ - "artifact_id":"svc:checkout@1.9.0", - "purl":"pkg:npm/lodash@4.17.20", - "advisory_key":"CVE-2025-12345", - "policy_version":"1.3.0", - "max_options":5, - "strategy_preference":["upgrade","backport","workaround"] -} --> 200 { "plan_text":"...", "plan": {RemediationPlan} } - -POST /advisory/ai/batch -{ - "items":[ {tuple}, {tuple}, ... ], - "task":"summary | conflict | remediation", - "policy_version":"1.3.0" -} --> 207 multi-status -``` - -Status codes: `400` invalid, `403` RBAC, `404` missing evidence, `409` conflict lock, `422` output validation failed, `429` rate limit. - -### 3.5 Console (Web UI) - -* Surfaces: - - * Vuln Explorer detail: “Advisory AI” side panel with 3 tabs: Summary, Conflict, Remediation. - * Consensus Lens detail: prominent “Explain conflict” button. - * Policy Studio sim: “Show effect on assistant output” preview. - -* UX details: - - * Citations are footnotes with hover to show source paragraph. - * “Copy as ticket” produces Markdown and JSON. - * Plan options show feasibility bar, blast radius chips, and required approvals per policy. - * Injection warnings appear if advisory text included unsafe instructions. - -* A11y: ARIA tags for tabs, keyboard shortcuts `G` to generate, `R` to refresh, `C` to copy JSON. - -### 3.6 CLI - -``` -stella advise summarize --advisory CVE-2025-12345 --artifact svc:checkout@1.9.0 --purl pkg:npm/lodash@4.17.20 --policy 1.3.0 --json -stella advise explain --advisory CVE-2025-12345 --artifact svc:checkout@1.9.0 --purl pkg:npm/lodash@4.17.20 --policy 1.3.0 -stella advise remediate --advisory CVE-2025-12345 --artifact svc:checkout@1.9.0 --purl pkg:npm/lodash@4.17.20 --policy 1.3.0 --strategy upgrade,workaround --out plan.json -stella advise batch --file tuples.json --task remediation --policy 1.3.0 -``` - -Exit codes: `0` ok, `2` invalid args, `4` not found, `5` denied, `7` validation fail. - -### 3.7 RBAC and security - -* Roles: - - * Viewer can run summaries and read explanations. - * Operator can run remediation and export plans. - * Admin can toggle model endpoints and guardrail settings. - -* Defaults: - - * Remote model calls disabled. - * Redaction on. - * Prompt logging anonymized. - * Outputs stored as derived artifacts with TTL (default 30 days) unless pinned to a ticket. - -### 3.8 Observability - -* Metrics: - - * `advisory_ai_latency_ms` by task type. - * `advisory_ai_guardrail_blocks_total`. - * `advisory_ai_output_validation_fail_total`. - * `advisory_ai_citation_coverage` gauge. -* Traces: retriever spans, tool calls, model inference, validator. -* Logs: include tuple key, token usage, truncation events, and guardrail outcomes. - -### 3.9 Performance - -* Targets: - - * P95 under 1.5 s for Summary and Conflict with warm caches. - * P95 under 2.5 s for Remediation on medium SBOMs (1000 packages). - * Batch throughput 10 tuples per second per worker. - -### 3.10 Edge cases - -* Advisory missing fixed versions: produce workaround‑only plan and mark feasibility low. -* Conflicts with near‑tie weights: declare “DISPUTED” and require human approval, no auto plan preferred. -* Exotic version schemes: fallback to string compare with warning and feasibility cap. -* Private packages: no public release notes. Prefer internal changelog links if attached to artifact metadata. -* Multi‑env differences: render per‑env deltas when policy knobs differ (dev vs prod). - ---- - -## 4) Implementation plan - -### 4.1 Services and components - -* **New:** `src/AdvisoryAI/StellaOps.AdvisoryAI` - - * `retriever/` wrappers for Conseiller, Excitator, VEX Lens, SBOM. - * `deterministic/` version and path analyzers. - * `orchestrator/` task routers and prompt builders. - * `guardrails/` injection, redaction, output validator. - * `api/` REST endpoints and schema enforcement. - -* **Updates:** - - * Conseiller: expose paragraph‑level anchors for advisories. - * Excitator: expose justifications and product trees in normalized form. - * VEX Lens: stable API for quorum and rationale. - * SBOM Service: efficient path queries and versions timeline per purl. - -### 4.2 Packaging - -* Container images: - - * `stella/advisory-ai:<>` - * `stella/inference:<>` (if using on‑prem model) -* Helm values to toggle remote inference and GPU. - -### 4.3 Rollout - -* Phase 1: Summary and Conflict read‑only. -* Phase 2: Remediation with “Copy as ticket”. -* Phase 3: Batch APIs, CLI, and Policy Studio simulation hooks. - ---- - -## 5) Documentation changes - -Create or update the following files. Each doc ends with the imposed rule statement. - -1. `/docs/advisory-ai/overview.md` - What it is, capabilities, guardrails, AOC alignment, RBAC. - -2. `/docs/advisory-ai/architecture.md` - RAG design, retrievers, orchestrator, deterministics, models, caching. - -3. `/docs/advisory-ai/api.md` - Endpoint specs, payload schemas, error codes, examples. - -4. `/docs/advisory-ai/console.md` - Screens, actions, a11y, how citations work, copy‑as‑ticket. - -5. `/docs/advisory-ai/cli.md` - Command usage, exit codes, piping examples. - -6. `/docs/policy/assistant-parameters.md` - Temperature, max tokens, plan ranking weights, TTLs. - -7. `/docs/security/assistant-guardrails.md` - Redaction rules, injection defense, output validation, logging. - -8. `/docs/sbom/remediation-heuristics.md` - Feasibility scoring, blast radius, effort classes. - -9. `/docs/runbooks/assistant-ops.md` - Warmup, cache priming, model outages, scaling, on‑call steps. - ---- - -## 6) Engineering tasks - -### Backend core - -* [ ] Implement structured and vector retrievers with paragraph anchors from Conseiller. -* [ ] Implement VEX retriever using Lens APIs with caching. -* [ ] Build deterministics: ecosystem comparators, range checks, dependency path scorer. -* [ ] Implement orchestrator with task‑specific templates and tool call pipeline. -* [ ] Implement guardrails and validators with hard failure on invalid JSON. -* [ ] Add RBAC to endpoints and anonymized prompt logging. -* [ ] Add caching layer with tuple‑keyed entries and policy version scoping. - -### Integrations - -* [ ] Conseiller: expose advisory chunk API and metadata needed for citations. -* [ ] Excitator: ensure justifications and product trees are queryable. -* [ ] VEX Lens: add “policy factors” endpoint for explanation rendering. -* [ ] SBOM Service: implement `GET /sbom/paths?purl=...` and version timeline. - -### Console - -* [ ] Build Advisory AI panel with 3 tabs and citation tooltips. -* [ ] Implement “Copy as ticket” (Markdown + JSON) and download. -* [ ] Add injection warning banner when triggered. -* [ ] Respect a11y requirements and shortcuts. - -### CLI - -* [ ] `stella advise summarize|explain|remediate|batch` with JSON output. -* [ ] Add `--out` option to save plans and summaries. -* [ ] Tests for piping and jq workflows. - -### Observability - -* [ ] Emit metrics and traces listed in §3.8. -* [ ] Dashboards: latency, guardrail blocks, validation fails, coverage. - -### Docs - -* [ ] Write all files in §5 with examples and screenshots. -* [ ] Cross‑link to VEX Lens and Vulnerability Explorer docs. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Acceptance criteria - -* Summaries cite specific source sections and reflect affected ranges and fixed versions correctly for at least 95% of a validation set. -* Conflict explanations enumerate issuers, weights, justifications, mapping issues, and policy thresholds that caused the consensus state. -* Remediation plans output at least one feasible option when a fixed version exists and correctly flag “no public fix” cases. -* JSON schemas validate for all outputs. -* Console shows the panel with citations, copy‑as‑ticket, and a11y passes. -* CLI produces identical JSON to API responses. -* Guardrails block injection attempts and redact secrets in prompts. -* P95 latency targets are met with warm caches. -* No mutation of raw advisory or VEX evidence occurs anywhere in the pipeline. - ---- - -## 8) Risks and mitigations - -* **Prompt injection in advisory text.** Strip instructions, sandbox chunks, and highlight to user when removed. -* **Hallucinated facts.** Hard validation requires facts to appear in structured inputs or cited text. Fail closed if not provable. -* **Mapping errors produce bad hints.** Depend on SBOM Graph and VEX Lens scope scores; cap feasibility when scope is weak. -* **Model outage.** Degrade to deterministic summaries (shorter, but accurate). -* **Privacy concerns.** Default on‑prem inference, remote endpoints opt‑in with clear flags and audit logs. - ---- - -## 9) Test plan - -* **Unit:** version comparators, range checks, feasibility scoring, output validators. -* **Golden files:** advisory sets mapped to expected summaries and plans; diff on each build. -* **Injection tests:** adversarial advisories with “ignore prior instructions” payloads must be neutralized. -* **Integration:** Conseiller→Advisory AI→Console loop, with VEX Lens conflicts and SBOM graph lookups. -* **E2E:** generate summary, explanation, and plan for representative ecosystems (npm, Maven, PyPI, Go, RPM/DEB). -* **Perf:** soak tests with 5k tuples batch; observe cache hit ratios and P95. -* **A11y:** keyboard navigation and screen reader labels. - ---- - -## 10) Philosophy - -* **Facts first.** If it is not in structured inputs or citations, it does not exist. -* **Explain everything.** Humans should see exactly why the tool said what it said. -* **Helpful by default.** Plans must consider the real dependency graph and environment, not fantasy. -* **No silent merges.** Evidence is sacred. Summaries and plans are separate, auditable derivatives. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EPIC_9.md b/docs/implplan/EPIC_9.md deleted file mode 100644 index 199d1458..00000000 --- a/docs/implplan/EPIC_9.md +++ /dev/null @@ -1,523 +0,0 @@ -Below is the “maximum documentation” bundle for Epic 9. Paste it into your repo and pretend the ingestion chaos was always under control. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 9: Source & Job Orchestrator Dashboard - -**Short name:** `Orchestrator Dashboard` -**Primary service:** `orchestrator` (scheduler, queues, rate‑limits, job state) -**Surfaces:** Console (Web UI), CLI, Web API -**Touches:** Conseiller (Feedser), Excitator (Vexer), VEX Consensus Lens, SBOM Service, Policy Engine, Findings Ledger, Authority (authN/Z), Telemetry/Analytics, Object Storage, Relational DB, Message Bus - -**AOC ground rule:** Conseiller and Excitator aggregate but never merge. The orchestrator schedules, tracks and recovers jobs; it does not transform evidence beyond transport and storage. No “smart” merging in flight. - ---- - -## 1) What it is - -The Source & Job Orchestrator Dashboard is the control surface for every data source and pipeline run across StellaOps. It gives operators: - -* Live health of all advisory/VEX/SBOM sources and derived jobs. -* End‑to‑end pipeline visibility as DAGs and timelines. -* Controls for pausing, backfilling, replaying, throttling and retrying. -* Error pattern analysis, rate‑limit observability and backpressure insights. -* Provenance and audit trails from initial fetch through parse, normalize, index and policy evaluation. - -The dashboard sits over the `orchestrator` service, which maintains job state, schedules runs, enforces quotas and rate limits, and collects metrics from worker pools embedded in Conseiller, Excitator, SBOM and related services. - ---- - -## 2) Why (brief) - -Ingestion breaks quietly and then loudly. Without a unified control plane, you learn about it from angry users or empty indexes. This dashboard shortens incident MTTR, enables safe backfills, and makes compliance reviewers stop sending emails with twelve attachments and one emoji. - ---- - -## 3) How it should work (maximum detail) - -### 3.1 Capabilities - -* **Source registry** - - * Register, tag and version connectors (OSV, GHSA, CSAF endpoints, vendor PDF scrapers, distro feeds, RSS, S3 drops, internal registries). - * Store connection details, secrets (via KMS), rate‑limit policy, schedules, and ownership metadata. - * Validate and “test connection” safely. - -* **Job orchestration** - - * Create DAGs composed of job types: `fetch`, `parse`, `normalize`, `dedupe`, `index`, `consensus_compute`, `policy_eval`, `crosslink`, `sbom_ingest`, `sbom_index`. - * Priorities, queues, concurrency caps, exponential backoff, circuit breakers. - * Idempotency keys and output artifact hashing to avoid duplicate work. - * Event‑time watermarks for backfills without double counting. - -* **Observability & control** - - * Gantt timeline and real‑time DAG view with critical path highlighting. - * Backpressure and queue depth heatmaps. - * Error clustering by class (HTTP 429, TLS, schema mismatch, parse failure, upstream 5xx). - * Per‑source SLOs and SLA budgets with burn‑rate alerts. - * One‑click actions: retry, replay range, pause/resume, throttle/unthrottle, reroute to canary workers. - -* **Provenance & audit** - - * Immutable run ledger linking input artifact → every job → output artifact. - * Schema version tracking and drift detection. - * Operator actions recorded with reason and ticket reference. - -* **Safety** - - * Secret redaction everywhere. - * Tenant isolation at API, queue and storage layers. - * AOC: no in‑flight merges of advisory or VEX content. - -### 3.2 Core architecture - -* **orchestrator (service)** - - * Maintains job state in Postgres (`sources`, `runs`, `jobs`, `artifacts`, `dag_edges`, `quotas`, `schedules`). - * Publishes work to a message bus (e.g., `topic.jobs.ready.`). - * Distributed token‑bucket rate limiter per source/tenant/host. - * Watchdog for stuck jobs and circuit breakers for flapping sources. - * Watermark manager for backfills (event‑time windows). - -* **worker SDK** - - * Lightweight library embedded in Conseiller/Excitator/SBOM workers to: - - * Claim work, heartbeat, update progress, report metrics. - * Emit artifact metadata and checksums. - * Enforce idempotency via orchestrator‑supplied key. - -* **object store** - - * Raw payloads and intermediate artifacts organized by schema and hash: - - * `advisory/raw///.json|pdf` - * `advisory/normalized//.json` - * `vex/raw|normalized/...` - * `sbom/raw|graph/...` - -* **web API** - - * CRUD for sources, runs, jobs, schedules, quotas. - * Control actions (retry, cancel, pause, backfill). - * Streaming updates via WebSocket/SSE for the Console. - -* **console** - - * React app consuming Orchestrator APIs, rendering DAGs, timelines, health charts and action panels with RBAC. - -### 3.3 Data model (selected tables) - -* `sources` - - * `id`, `kind` (`advisory|vex|sbom|internal`), `subtype` (e.g., `osv`, `ghsa`, `csaf`, `vendor_pdf`), `display_name`, `owner_team`, `schedule_cron`, `rate_policy`, `enabled`, `secrets_ref`, `tags`, `schema_hint`, `created_at`, `updated_at`. - -* `runs` - - * `id`, `source_id`, `trigger` (`schedule|manual|event|backfill`), `window_start`, `window_end`, `state`, `started_at`, `finished_at`, `stats_json`. - -* `jobs` - - * `id`, `run_id`, `type`, `queue`, `priority`, `state` (`pending|running|succeeded|failed|canceled|deadletter`), `attempt`, `max_attempt`, `idempotency_key`, `input_artifact_id`, `output_artifact_id`, `worker_id`, `created_at`, `started_at`, `finished_at`, `error_class`, `error_message`, `metrics_json`. - -* `dag_edges` - - * `from_job_id`, `to_job_id`, `edge_kind` (`success_only|always`). - -* `artifacts` - - * `id`, `kind` (`raw|normalized|index|consensus`), `schema_ver`, `hash`, `uri`, `bytes`, `meta_json`, `created_at`. - -* `quotas` - - * `tenant_id`, `resource` (`requests_per_min`, `concurrent_jobs`), `limit`, `window_sec`. - -* `schedules` - - * Per‑source cron plus jitter, timezone, blackout windows. - -### 3.4 Job lifecycle - -1. **Plan** - Scheduler creates a `run` for a source and plans a DAG: e.g., `fetch → parse → normalize → dedupe → index → policy_eval` (advisory) or `fetch → parse → normalize → consensus_compute` (VEX). - -2. **Enqueue** - Ready nodes become `jobs` with queue, priority, idempotency key and optional rate‑limit tokens reserved. - -3. **Execute** - Worker claims job, heartbeats every N seconds. Output artifacts are stored and linked. Failures are classified and retried with exponential backoff and jitter, up to `max_attempt`. - -4. **Complete** - Downstream nodes unblock. On run completion, orchestrator computes SLO deltas and emits run summary. - -5. **Dead‑letter** - Jobs exceeding attempts move to a DLQ with structured context and suggested remediation. - -### 3.5 Scheduling, backpressure, rate‑limits - -* **Token bucket** per `{tenant, source.host}` with adaptive refill if upstream 429/503 seen. -* **Concurrency caps** per source and per job type to avoid thundering herd. -* **Backpressure signals** from queue depth, worker CPU, and upstream error rates; scheduler reduces inflight issuance accordingly. -* **Backfills** use event‑time windows with immutable watermarks to avoid re‑processing. -* **Blackout windows** for vendor maintenance periods. - -### 3.6 APIs - -``` -POST /orchestrator/sources -GET /orchestrator/sources?kind=&tag=&q= -GET /orchestrator/sources/{id} -PATCH /orchestrator/sources/{id} -POST /orchestrator/sources/{id}/actions:test|pause|resume|sync-now -POST /orchestrator/sources/{id}/backfill { "from":"2024-01-01", "to":"2024-03-01" } - -GET /orchestrator/runs?source_id=&state=&from=&to= -GET /orchestrator/runs/{run_id} -GET /orchestrator/runs/{run_id}/dag -POST /orchestrator/runs/{run_id}/cancel - -GET /orchestrator/jobs?state=&type=&queue=&source_id= -GET /orchestrator/jobs/{job_id} -POST /orchestrator/jobs/{job_id}/actions:retry|cancel|prioritize - -GET /orchestrator/metrics/overview -GET /orchestrator/errors/top?window=1h -GET /orchestrator/quotas -PATCH /orchestrator/quotas/{tenant_id} -WS /orchestrator/streams/updates -``` - -### 3.7 Console (Web UI) - -* **Overview** - - * KPI tiles: sources healthy, runs in progress, queue depth, error rate, burn‑rate to SLO. - * Heatmap of source health by last 24h success ratio. - -* **Sources** - - * Grid with filters, inline status (active, paused, throttled), next run eta, last error class. - * Detail panel: config, secrets status (redacted), schedule, rate limits, ownership, run history, action buttons. - -* **Runs** - - * Timeline (Gantt) with critical path, duration distribution, and per‑stage breakdown. - * Run detail: DAG view with node metrics, artifacts, logs, action menu (cancel). - -* **Jobs** - - * Live table with state filters and “tail” view. - * Job detail: payload preview (redacted), worker, attempts, stack traces, linked artifacts. - -* **Errors** - - * Clusters by class and signature, suggested remediations (pause source, lower concurrency, patch parser). - -* **Queues & Backpressure** - - * Per‑queue depth, service rate, inflight, age percentiles. - * Rate‑limit tokens graphs per source host. - -* **Controls** - - * Backfill wizard with event‑time preview and safety checks. - * Canary routing: route 5% of next 100 runs to a new worker pool. - -* **A11y** - - * Keyboard nav, ARIA roles for DAG nodes, live regions for updates, color‑blind friendly graphs. - -### 3.8 CLI - -``` -stella orch sources list --kind advisory --tag prod -stella orch sources add --file source.yaml -stella orch sources test -stella orch sources pause # or resume -stella orch sources sync-now -stella orch sources backfill --from 2024-01-01 --to 2024-03-01 - -stella orch runs list --source --state running -stella orch runs show --dag -stella orch runs cancel - -stella orch jobs list --state failed --type parse --limit 100 -stella orch jobs retry -stella orch jobs cancel -stella orch jobs tail --queue normalize --follow - -stella orch quotas get --tenant default -stella orch quotas set --tenant default --concurrent-jobs 50 --rpm 1200 -``` - -Exit codes: `0` success, `2` invalid args, `4` not found, `5` denied, `7` precondition failed, `8` rate‑limited. - -### 3.9 RBAC & security - -* **Roles** - - * `Orch.Viewer`: read‑only sources/runs/jobs/metrics. - * `Orch.Operator`: perform actions on sources and jobs, launch backfills. - * `Orch.Admin`: manage quotas, schedules, connector versions, and delete sources. - -* **Secrets** - - * Stored only as references to your KMS; never persisted in cleartext. - * Console shows redact badges and last rotated timestamp. - -* **Tenancy** - - * Source, run, job rows scoped by tenant id. - * Queue names and token buckets namespaced per tenant. - -* **Compliance** - - * Full audit log for every operator action with “reason” and optional ticket link. - * Exportable run ledger for audits. - -### 3.10 Observability - -* **Metrics (examples)** - - * `orch_jobs_inflight{type,queue}` - * `orch_jobs_latency_ms{type,percentile}` - * `orch_rate_tokens_available{source}` - * `orch_error_rate{source,error_class}` - * `orch_slo_burn_rate{source,slo}` - * `orch_deadletter_total{source,type}` - -* **Traces** - - * Span per job with baggage: `run_id`, `source_id`, `artifact_id`. - * Links across services to Conseiller/Excitator/SBOM workers. - -* **Logs** - - * Structured JSON with correlation ids, attempt numbers and redacted payload previews. - -### 3.11 Performance targets - -* Job dispatch P95 < 150 ms after dependency satisfied. -* Scheduler loop P95 < 500 ms for 10k pending jobs. -* Console live updates sub‑second at 1k events/sec per tenant. -* Backfill throughput ≥ 200 jobs/sec per worker pool with zero dupes. - -### 3.12 Edge cases & behaviors - -* **Upstream 429 storms:** auto‑throttle, pause optional, recommend extended jitter. -* **Schema drift:** parser moves job to DLQ with `error_class=schema_mismatch` and opens a change ticket via webhook. -* **Flapping source:** circuit breaker opens after N consecutive failures; requires human “resume”. -* **Clock skew:** watermark logic uses upstream event time; large skews flagged. -* **Idempotency collisions:** new attempt yields no‑op if artifact hash already exists. - ---- - -## 4) Implementation plan - -### 4.1 Modules (new and updated) - -* New service: `src/Orchestrator/StellaOps.Orchestrator` - - * `api/` REST + WS handlers - * `scheduler/` run planner, DAG builder, watermark/backfill logic - * `queues/` publisher and consumer abstractions - * `ratelimit/` token bucket and adaptive controller - * `state/` Postgres repositories and migrations - * `audit/` action logging and export - * `metrics/` Prometheus exporters - * `security/` tenant scoping, KMS client, secret refs - -* Worker SDKs: - - * `src/Orchestrator/StellaOps.Orchestrator.WorkerSdk.Go` and `src/Orchestrator/StellaOps.Orchestrator.WorkerSdk.Python` with job claim, heartbeat, progress, artifact publish, and structured error reporting. - -* Console: - - * `console/apps/orch/` pages: Overview, Sources, Runs, Jobs, Errors, Queues. - * `components/dag-view/`, `components/gantt/`, `components/health-heatmap/`. - -* Updates to existing services: - - * Conseiller/Excitator/SBOM workers adopt SDK and emit artifacts with schema/version/fingerprint. - * VEX Lens exposes `consensus_compute` as a jobable operation. - * Policy Engine exposes `policy_eval` as a job type for scheduled recalcs. - -### 4.2 Packaging & deployment - -* Containers: - - * `stella/orchestrator:` - * `stella/worker-sdk-examples:` for canary pools - -* Helm values: - - * Queues/topics, per‑tenant concurrency, rate‑limit defaults, WS replica count. - * KMS integration secrets. - -* Migrations: - - * Flyway/Goose migrations for new tables and indexes. - -### 4.3 Rollout strategy - -* Phase 1: Read‑only dashboard fed by existing job tables; no controls. -* Phase 2: Control actions enabled for non‑prod tenants. -* Phase 3: Backfills and quota management, then GA. - ---- - -## 5) Documentation changes - -Create/update the following, each ending with the imposed rule statement. - -1. `/docs/orchestrator/overview.md` - Concepts, roles, responsibilities, AOC alignment. - -2. `/docs/orchestrator/architecture.md` - Scheduler, DAGs, watermarks, queues, rate‑limits, data model. - -3. `/docs/orchestrator/api.md` - Endpoints, WebSocket events, error codes, examples. - -4. `/docs/orchestrator/console.md` - Screens, actions, a11y, live updates. - -5. `/docs/orchestrator/cli.md` - Commands, examples, exit codes, scripting patterns. - -6. `/docs/orchestrator/run‑ledger.md` - Provenance and audit export format. - -7. `/docs/security/secrets‑handling.md` - KMS references, redaction rules, operator hygiene. - -8. `/docs/operations/orchestrator‑runbook.md` - Common failures, backfill guide, circuit breakers, tuning. - -9. `/docs/schemas/artifacts.md` - Artifact kinds, schema versions, hashing, storage layout. - -10. `/docs/slo/orchestrator‑slo.md` - SLO definitions, measurement, alerting. - ---- - -## 6) Engineering tasks - -### Backend (orchestrator) - -* [ ] Stand up Postgres schemas and indices for sources, runs, jobs, dag_edges, artifacts, quotas, schedules. -* [ ] Implement scheduler: DAG planner, dependency resolver, critical path computation. -* [ ] Implement rate limiter with adaptive behavior on 429/503 and per‑tenant tokens. -* [ ] Implement watermark/backfill manager with event‑time windows and idempotency keys. -* [ ] Implement API endpoints + OpenAPI spec + request validation. -* [ ] Implement WebSocket/SSE event stream for live updates. -* [ ] Implement audit logging and export. -* [ ] Implement dead‑letter store and replay. - -### Worker SDKs and integrations - -* [ ] Build Go/Python SDKs with claim/heartbeat/progress API. -* [ ] Integrate SDK into Conseiller, Excitator, SBOM workers; ensure artifact emission with schema ver. -* [ ] Add `consensus_compute` and `policy_eval` as job types with deterministic inputs/outputs. - -### Console - -* [ ] Overview tiles and health heatmap. -* [ ] Source list/detail with actions and config view. -* [ ] Runs timeline (Gantt) and DAG visualization with node inspector. -* [ ] Jobs “tail” with live updates and filters. -* [ ] Errors clustering and suggested remediations. -* [ ] Queues/backpressure dashboard. -* [ ] Backfill wizard with safety checks. - -### Observability - -* [ ] Emit metrics listed in §3.10 and wire traces across services. -* [ ] Dashboards: health, queue depth, error classes, burn‑rate, dispatch latency. -* [ ] Alerts for SLO burn and circuit breaker opens. - -### Security & RBAC - -* [ ] Enforce tenant scoping on all endpoints; test leakage. -* [ ] Wire KMS for secret refs and redact everywhere. -* [ ] Implement `Orch.Viewer|Operator|Admin` roles and check in Console and API. - -### Docs - -* [ ] Author all files in §5 with examples and screenshots. -* [ ] Cross‑link from Conseiller/Excitator/SBOM pages to the dashboard docs. -* [ ] Append imposed rule to each page. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -## 7) Acceptance criteria - -* Operators can: pause/resume a source, run “sync‑now,” initiate a backfill for a date range, and retry/cancel individual jobs from Console and CLI. -* DAG and timeline reflect reality within 1 second of job state changes at P95. -* Backfills do not create duplicate artifacts; idempotency proven by hash equality. -* Rate limiter reduces 429s by ≥80% under simulated throttle tests. -* Audit log includes who/when/why for every operator action. -* Provenance ledger exports a complete chain for any artifact. -* RBAC prevents non‑admins from quota changes; tenancy isolation proven via automated tests. -* SLO dashboard shows burn‑rate and triggers alerts under injected failure. - ---- - -## 8) Risks & mitigations - -* **Orchestrator becomes a single bottleneck.** - Horizontal scale stateless workers; DB indexes tuned; job state updates batched; cache hot paths. - -* **Secret spillage.** - Only KMS references stored; aggressive redaction; log scrubbing in SDK. - -* **Over‑eager backfills overwhelm upstream.** - Enforce per‑source quotas and sandbox previews; dry‑run backfills first. - -* **Schema drift silently corrupts normalization.** - Hard‑fail on mismatch; DLQ with clear signatures; schema registry gating. - -* **Flapping sources cause alert fatigue.** - Circuit breaker with cool‑down and deduped alerts; error budget policy. - ---- - -## 9) Test plan - -* **Unit** - Scheduler DAG building, topological sort, backoff math, token bucket, watermark math. - -* **Integration** - Orchestrator ↔ worker SDK, artifact store wiring, DLQ replay, audit pipeline. - -* **Chaos** - Inject 429 storms, packet loss, worker crashes; verify throttling and recovery. - -* **Backfill** - Simulate overlapping windows and verify idempotency and watermark correctness. - -* **Perf** - 10k concurrent jobs: dispatch latency, DB contention, WebSocket fan‑out. - -* **Security** - Multi‑tenant isolation tests; KMS mock tests for secret access; RBAC matrix. - -* **UX/A11y** - Screen reader labels on DAG, keyboard navigation, live region updates. - ---- - -## 10) Philosophy - -* **Make the invisible visible.** Pipelines should be legible at a glance. -* **Prefer reproducibility to heroics.** Idempotency and provenance over “we think it ran.” -* **Safeguards before speed.** Throttle first, retry thoughtfully, never melt upstreams. -* **No silent merges.** Evidence remains immutable; transformations are explicit, logged and reversible. - -> Final reminder: **Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.** diff --git a/docs/implplan/EXECPLAN.md b/docs/implplan/EXECPLAN.md index eca9b102..95e420ad 100644 --- a/docs/implplan/EXECPLAN.md +++ b/docs/implplan/EXECPLAN.md @@ -1244,7 +1244,7 @@ Generated from SPRINTS.md and module TASKS.md files on 2025-10-19. Waves cluster 5. [TODO] DOCS-POLICY-20-005 — `/docs/api/policy.md` endpoints + schemas. • Prereqs: WEB-POLICY-20-001 (Wave 7) • Current: TODO - 6. [TODO] DOCS-POLICY-20-006 — `/docs/cli/policy.md` with command usage. + 6. [TODO] DOCS-POLICY-20-006 — `/docs/modules/cli/guides/policy.md` with command usage. • Prereqs: CLI-POLICY-20-002 (Wave 7) • Current: TODO 7. [TODO] DOCS-POLICY-20-007 — `/docs/ui/policy-editor.md` flows + screenshots. diff --git a/docs/implplan/SPRINTS.md b/docs/implplan/SPRINTS.md index 80fbf844..b553df88 100644 --- a/docs/implplan/SPRINTS.md +++ b/docs/implplan/SPRINTS.md @@ -535,9 +535,9 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 35 | EPDR Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.DotNet/TASKS.md | TODO | Scanner EPDR Guild | SCANNER-ANALYZERS-LANG-11-001 | Build entrypoint resolver (identity + environment profiles) and emit normalized entrypoint records. | | Sprint 35 | EPDR Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.DotNet/TASKS.md | TODO | Scanner EPDR Guild | SCANNER-ANALYZERS-LANG-11-002 | Static IL/reflection/ALC heuristics producing dependency edges with reason codes and confidence. | | Sprint 35 | EPDR Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.DotNet/TASKS.md | TODO | Scanner EPDR Guild, Signals Guild | SCANNER-ANALYZERS-LANG-11-003 | Runtime loader/PInvoke signal ingestion merged with static/declared edges (confidence & explain). | -| Sprint 35 | Export Center Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-35-001 | Author `/docs/export-center/overview.md` with purpose, profiles, security, and imposed rule reminder. | -| Sprint 35 | Export Center Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-35-002 | Author `/docs/export-center/architecture.md` detailing service components, adapters, manifests, signing, and distribution. | -| Sprint 35 | Export Center Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-35-003 | Publish `/docs/export-center/profiles.md` covering schemas, examples, and compatibility. | +| Sprint 35 | Export Center Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-35-001 | Author `/docs/modules/export-center/overview.md` with purpose, profiles, security, and imposed rule reminder. | +| Sprint 35 | Export Center Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-35-002 | Author `/docs/modules/export-center/architecture.md` detailing service components, adapters, manifests, signing, and distribution. | +| Sprint 35 | Export Center Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-35-003 | Publish `/docs/modules/export-center/profiles.md` covering schemas, examples, and compatibility. | | Sprint 35 | Export Center Phase 1 | ops/deployment/TASKS.md | TODO | Deployment Guild | DEPLOY-EXPORT-35-001 | Package exporter service/worker containers, Helm overlays (download-only), and rollout guide. | | Sprint 35 | Export Center Phase 1 | ops/devops/TASKS.md | TODO | DevOps Guild | DEVOPS-EXPORT-35-001 | Create exporter CI pipeline (lint/test/perf smoke), object storage fixtures, and initial Grafana dashboards. | | Sprint 35 | Export Center Phase 1 | src/ExportCenter/StellaOps.ExportCenter/TASKS.md | TODO | Exporter Service Guild | EXPORT-SVC-35-001 | Bootstrap exporter service, configuration, and migrations for export profiles/runs/inputs/distributions with tenant scopes. | @@ -553,9 +553,9 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 35 | Export Center Phase 1 | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild | WEB-EXPORT-35-001 | Route Export Center APIs through gateway with tenant scoping, viewer/operator scopes, and streaming downloads. | | Sprint 36 | EPDR Observations | src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.DotNet/TASKS.md | TODO | Scanner EPDR Guild, SBOM Service Guild | SCANNER-ANALYZERS-LANG-11-004 | Normalize EPDR output to Scanner observation writer (entrypoints + edges + env profiles). | | Sprint 36 | EPDR Observations | src/Scanner/__Libraries/StellaOps.Scanner.Analyzers.Lang.DotNet/TASKS.md | TODO | Scanner EPDR Guild, QA Guild | SCANNER-ANALYZERS-LANG-11-005 | End-to-end fixtures/benchmarks covering publish modes, RIDs, trimming, NativeAOT with explain traces. | -| Sprint 36 | Export Center Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-36-004 | Author `/docs/export-center/api.md` with endpoint examples and imposed rule note. | -| Sprint 36 | Export Center Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-36-005 | Publish `/docs/export-center/cli.md` covering commands, scripts, verification, and imposed rule reminder. | -| Sprint 36 | Export Center Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-36-006 | Write `/docs/export-center/trivy-adapter.md` detailing mappings, compatibility, and test matrix. | +| Sprint 36 | Export Center Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-36-004 | Author `/docs/modules/export-center/api.md` with endpoint examples and imposed rule note. | +| Sprint 36 | Export Center Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-36-005 | Publish `/docs/modules/export-center/cli.md` covering commands, scripts, verification, and imposed rule reminder. | +| Sprint 36 | Export Center Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-36-006 | Write `/docs/modules/export-center/trivy-adapter.md` detailing mappings, compatibility, and test matrix. | | Sprint 36 | Export Center Phase 2 | ops/deployment/TASKS.md | TODO | Deployment Guild | DEPLOY-EXPORT-36-001 | Document registry credentials, OCI push workflows, and automation for export distributions. | | Sprint 36 | Export Center Phase 2 | ops/devops/TASKS.md | TODO | DevOps Guild | DEVOPS-EXPORT-36-001 | Integrate Trivy compatibility validation, OCI push smoke tests, and metrics dashboards for export throughput. | | Sprint 36 | Export Center Phase 2 | src/Cli/StellaOps.Cli/TASKS.md | TODO | DevEx/CLI Guild | CLI-EXPORT-36-001 | Add `stella export distribute` (OCI/objstore), `run download --resume`, and status polling enhancements. | @@ -565,8 +565,8 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 36 | Export Center Phase 2 | src/ExportCenter/StellaOps.ExportCenter/TASKS.md | TODO | Exporter Service Guild | EXPORT-SVC-36-004 | Extend planner/run lifecycle for OCI/object storage distributions with retry + idempotency. | | Sprint 36 | Export Center Phase 2 | src/Orchestrator/StellaOps.Orchestrator/TASKS.md | TODO | Orchestrator Service Guild | ORCH-SVC-36-101 | Add distribution job follow-ups, retention metadata, and metrics for export runs. | | Sprint 36 | Export Center Phase 2 | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild | WEB-EXPORT-36-001 | Expose distribution endpoints (OCI/object storage) and manifest/provenance download proxies with RBAC. | -| Sprint 37 | Export Center Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-37-001 | Publish `/docs/export-center/mirror-bundles.md` detailing layouts, deltas, encryption, imposed rule reminder. | -| Sprint 37 | Export Center Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-37-002 | Publish `/docs/export-center/provenance-and-signing.md` covering manifests, attestation, verification. | +| Sprint 37 | Export Center Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-37-001 | Publish `/docs/modules/export-center/mirror-bundles.md` detailing layouts, deltas, encryption, imposed rule reminder. | +| Sprint 37 | Export Center Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-37-002 | Publish `/docs/modules/export-center/provenance-and-signing.md` covering manifests, attestation, verification. | | Sprint 37 | Export Center Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-37-003 | Publish `/docs/operations/export-runbook.md` for failures, tuning, capacity, with imposed rule note. | | Sprint 37 | Export Center Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-EXPORT-37-004 | Publish `/docs/security/export-hardening.md` covering RBAC, isolation, encryption, and imposed rule. | | Sprint 37 | Export Center Phase 3 | ops/devops/TASKS.md | TODO | DevOps Guild | DEVOPS-EXPORT-37-001 | Finalize dashboards/alerts for exports (failure, verify), retention jobs, and chaos testing harness. | @@ -631,7 +631,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 40 | Notifications Studio Phase 3 | src/Notifier/StellaOps.Notifier/TASKS.md | TODO | Notifications Service Guild | NOTIFY-SVC-40-003 | Harden security: signed ack links, webhook HMAC/IP allowlists, tenant isolation fuzzing, localization fallback. | | Sprint 40 | Notifications Studio Phase 3 | src/Notifier/StellaOps.Notifier/TASKS.md | TODO | Notifications Service Guild | NOTIFY-SVC-40-004 | Finalize observability (incident metrics, escalation latency) and chaos tests for channel outages. | | Sprint 40 | Notifications Studio Phase 3 | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild | WEB-NOTIFY-40-001 | Expose escalation, localization, channel health endpoints and verification of signed links. | -| Sprint 41 | CLI Parity & Task Packs Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-CLI-41-001 | Publish `/docs/cli/overview.md`, `/cli/configuration.md`, `/cli/output-and-exit-codes.md` (with imposed rule). | +| Sprint 41 | CLI Parity & Task Packs Phase 1 | docs/TASKS.md | TODO | Docs Guild | DOCS-CLI-41-001 | Publish `/docs/modules/cli/guides/overview.md`, `/cli/configuration.md`, `/cli/output-and-exit-codes.md` (with imposed rule). | | Sprint 41 | CLI Parity & Task Packs Phase 1 | ops/deployment/TASKS.md | TODO | Deployment Guild | DEPLOY-CLI-41-001 | Package CLI release artifacts (tarballs, completions, container image) with distribution docs. | | Sprint 41 | CLI Parity & Task Packs Phase 1 | ops/devops/TASKS.md | TODO | DevOps Guild | DEVOPS-CLI-41-001 | Establish CLI build pipeline (multi-platform binaries, SBOM, checksums) and parity matrix CI enforcement. | | Sprint 41 | CLI Parity & Task Packs Phase 1 | src/Authority/StellaOps.Authority/TASKS.md | TODO | Authority Core & Security Guild | AUTH-PACKS-41-001 | Define CLI SSO scopes and Packs (`Packs.Read/Write/Run/Approve`) roles; update discovery/offline defaults. | @@ -641,7 +641,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 41 | CLI Parity & Task Packs Phase 1 | src/Orchestrator/StellaOps.Orchestrator/TASKS.md | TODO | Orchestrator Service Guild | ORCH-SVC-41-101 | Register `pack-run` job type, integrate logs/artifacts, expose pack run metadata. | | Sprint 41 | CLI Parity & Task Packs Phase 1 | src/PacksRegistry/StellaOps.PacksRegistry/TASKS.md | TODO | Packs Registry Guild | PACKS-REG-41-001 | Implement packs index API, signature verification, provenance storage, and RBAC. | | Sprint 41 | CLI Parity & Task Packs Phase 1 | src/TaskRunner/StellaOps.TaskRunner/TASKS.md | TODO | Task Runner Guild | TASKRUN-41-001 | Bootstrap Task Runner service, migrations, run API, local executor, approvals pause, artifact capture. | -| Sprint 42 | CLI Parity & Task Packs Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-CLI-42-001 | Publish `/docs/cli/parity-matrix.md`, `/cli/commands/*.md`, `/docs/task-packs/spec.md` (imposed rule). | +| Sprint 42 | CLI Parity & Task Packs Phase 2 | docs/TASKS.md | TODO | Docs Guild | DOCS-CLI-42-001 | Publish `/docs/modules/cli/guides/parity-matrix.md`, `/cli/commands/*.md`, `/docs/task-packs/spec.md` (imposed rule). | | Sprint 42 | CLI Parity & Task Packs Phase 2 | ops/devops/TASKS.md | TODO | DevOps Guild | DEVOPS-CLI-42-001 | Add CLI golden output tests, parity diff automation, and pack run CI harness. | | Sprint 42 | CLI Parity & Task Packs Phase 2 | src/Cli/StellaOps.Cli/TASKS.md | TODO | DevEx/CLI Guild | CLI-PACKS-42-001 | Implement Task Pack CLI commands (`pack plan/run/push/pull/verify`) with plan/simulate engine and expression sandbox. | | Sprint 42 | CLI Parity & Task Packs Phase 2 | src/Cli/StellaOps.Cli/TASKS.md | TODO | DevEx/CLI Guild | CLI-PARITY-41-001..002 | Close parity gaps for Notifications, Policy Studio advanced features, SBOM graph, Vuln Explorer; parity matrix green. | @@ -695,7 +695,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 48 | Authority-Backed Scopes & Tenancy Phase 2 | src/Policy/StellaOps.Policy.Engine/TASKS.md | TODO | Policy Guild | POLICY-TEN-48-001 | Add `tenant_id`/`project_id` to policy data, enable Postgres RLS, and expose rationale IDs with tenant context. | | Sprint 48 | Authority-Backed Scopes & Tenancy Phase 2 | src/TaskRunner/StellaOps.TaskRunner/TASKS.md | TODO | Task Runner Guild | TASKRUN-TEN-48-001 | Propagate tenant/project to all steps, enforce object store prefix, and validate before execution. | | Sprint 48 | Authority-Backed Scopes & Tenancy Phase 2 | src/Web/StellaOps.Web/TASKS.md | TODO | BE-Base Platform Guild | WEB-TEN-48-001 | Enforce tenant context through persistence (DB GUC, object store prefix), add request annotations, and emit audit events. | -| Sprint 49 | Authority-Backed Scopes & Tenancy Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-TEN-49-001 | Publish `/docs/cli/authentication.md`, `/docs/api/authentication.md`, `/docs/policy/examples/abac-overlays.md`, `/docs/install/configuration-reference.md` updates (imposed rule). | +| Sprint 49 | Authority-Backed Scopes & Tenancy Phase 3 | docs/TASKS.md | TODO | Docs Guild | DOCS-TEN-49-001 | Publish `/docs/modules/cli/guides/authentication.md`, `/docs/api/authentication.md`, `/docs/policy/examples/abac-overlays.md`, `/docs/install/configuration-reference.md` updates (imposed rule). | | Sprint 49 | Authority-Backed Scopes & Tenancy Phase 3 | ops/devops/TASKS.md | TODO | DevOps Guild | DEVOPS-TEN-49-001 | Implement audit log pipeline, monitor scope usage, chaos tests for JWKS outage, and tenant load/perf tests. | | Sprint 49 | Authority-Backed Scopes & Tenancy Phase 3 | src/Authority/StellaOps.Authority/TASKS.md | TODO | Authority Core & Security Guild | AUTH-TEN-49-001 | Implement service accounts, delegation tokens (`act` chain), per-tenant quotas, and audit log streaming. | | Sprint 49 | Authority-Backed Scopes & Tenancy Phase 3 | src/Cli/StellaOps.Cli/TASKS.md | TODO | DevEx/CLI Guild | CLI-TEN-49-001 | Add service account token minting, delegation, and `--impersonate` banner/controls. | @@ -707,7 +707,7 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 50 | Observability & Forensics Phase 1 – Baseline Telemetry | docs/TASKS.md | TODO | Docs Guild | DOCS-OBS-50-004 | Publish tracing guide `/docs/observability/tracing.md` covering context propagation and sampling. | | Sprint 50 | Observability & Forensics Phase 1 – Baseline Telemetry | docs/TASKS.md | TODO | Docs Guild | DOCS-SEC-OBS-50-001 | Update `/docs/security/redaction-and-privacy.md` for telemetry privacy controls. | | Sprint 50 | Observability & Forensics Phase 1 – Baseline Telemetry | ops/devops/TASKS.md | DOING (2025-10-26) | DevOps Guild | DEVOPS-OBS-50-002 | Stand up multi-tenant metrics/logs/traces backends with retention and isolation. | -> Staging rollout plan recorded in `docs/ops/telemetry-storage.md`; waiting on Authority-issued tokens and namespace bootstrap. +> Staging rollout plan recorded in `docs/modules/telemetry/operations/storage.md`; waiting on Authority-issued tokens and namespace bootstrap. | Sprint 50 | Observability & Forensics Phase 1 – Baseline Telemetry | src/Authority/StellaOps.Authority/TASKS.md | TODO | Authority Core & Security Guild | AUTH-OBS-50-001 | Introduce observability/timeline/evidence/attestation scopes and update discovery metadata. | | Sprint 50 | Observability & Forensics Phase 1 – Baseline Telemetry | src/Cli/StellaOps.Cli/TASKS.md | TODO | DevEx/CLI Guild | CLI-OBS-50-001 | Propagate trace headers from CLI commands and print correlation IDs. | | Sprint 50 | Observability & Forensics Phase 1 – Baseline Telemetry | src/Concelier/__Libraries/StellaOps.Concelier.Core/TASKS.md | TODO | Concelier Core Guild | CONCELIER-OBS-50-001 | Replace ad-hoc logging with telemetry core across advisory ingestion/linking. | diff --git a/docs/implplan/SPRINTS_PRIOR_20251019.md b/docs/implplan/SPRINTS_PRIOR_20251019.md index 97bfd25c..c40bd458 100644 --- a/docs/implplan/SPRINTS_PRIOR_20251019.md +++ b/docs/implplan/SPRINTS_PRIOR_20251019.md @@ -36,7 +36,7 @@ Closed sprint tasks archived from SPRINTS.md on 2025-10-19. | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-003 | Telemetry & documentation
Apple meter metrics wired into Concelier WebService OpenTelemetry configuration; README and fixtures document normalizedVersions coverage. | | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md | DONE (2025-10-12) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-004 | Live HTML regression sweep
Sanitised HT125326/HT125328/HT106355/HT214108/HT215500 fixtures recorded and regression tests green on 2025-10-12. | | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md | DONE (2025-10-11) | Team Vendor Apple Specialists | FEEDCONN-APPLE-02-005 | Fixture regeneration tooling
`UPDATE_APPLE_FIXTURES=1` flow fetches & rewrites fixtures; README documents usage.
Instructions to work:
DONE Read ./AGENTS.md and src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Apple/AGENTS.md. Resume stalled tasks, ensuring normalizedVersions output and fixtures align with ./src/FASTER_MODELING_AND_NORMALIZATION.md before handing data to the conflict sprint. | -| Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance
Team instructions: Read ./AGENTS.md and each module's AGENTS file. Adopt the `NormalizedVersions` array emitted by the models sprint, wiring provenance `decisionReason` where merge overrides occur. Follow ./src/FASTER_MODELING_AND_NORMALIZATION.md; report via src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md (FEEDMERGE-COORD-02-900). Progress 2025-10-11: GHSA/OSV emit normalized arrays with refreshed fixtures; CVE mapper now surfaces SemVer normalized ranges; NVD/KEV adoption pending; outstanding follow-ups include FEEDSTORAGE-DATA-02-001, FEEDMERGE-ENGINE-02-002, and rolling `tools/FixtureUpdater` updates across connectors. | +| Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance
Team instructions: Read ./AGENTS.md and each module's AGENTS file. Adopt the `NormalizedVersions` array emitted by the models sprint, wiring provenance `decisionReason` where merge overrides occur. Follow ./src/FASTER_MODELING_AND_NORMALIZATION.md; report via src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md (FEEDMERGE-COORD-02-900). Progress 2025-10-11: GHSA/OSV emit normalized arrays with refreshed fixtures; CVE mapper now surfaces SemVer normalized ranges; NVD/KEV adoption pending; outstanding follow-ups include FEEDSTORAGE-DATA-02-001, FEEDMERGE-ENGINE-02-002, and rolling `src/Tools/FixtureUpdater` updates across connectors. | | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-OSV-02-003 | OSV normalized versions & freshness | | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-NVD-02-002 | NVD normalized versions & timestamps | | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Cve/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-CVE-02-003 | CVE normalized versions uplift | @@ -72,14 +72,14 @@ Closed sprint tasks archived from SPRINTS.md on 2025-10-19. | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv/TASKS.md | DONE (2025-10-11) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-004 | OSV references & credits alignment | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – GHSA/NVD/OSV | FEEDCONN-OSV-02-005 | Fixture updater workflow
Resolved 2025-10-12: OSV mapper now derives canonical PURLs for Go + scoped npm packages when raw payloads omit `purl`; conflict fixtures unchanged for invalid npm names. Verified via `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests`, `src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa.Tests`, `src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Nvd.Tests`, and backbone normalization/storage suites. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Acsc/TASKS.md | DONE (2025-10-12) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ACSC-02-001 … 02-008 | Fetch→parse→map pipeline, fixtures, diagnostics, and README finished 2025-10-12; downstream export parity captured via FEEDEXPORT-JSON-04-001 / FEEDEXPORT-TRIVY-04-001 (completed). | -| Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Cccs/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CCCS-02-001 … 02-008 | Observability meter, historical harvest plan, and DOM sanitizer refinements wrapped; ops notes live under `docs/ops/concelier-cccs-operations.md` with fixtures validating EN/FR list handling. | -| Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.CertBund/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CERTBUND-02-001 … 02-008 | Telemetry/docs (02-006) and history/locale sweep (02-007) completed alongside pipeline; runbook `docs/ops/concelier-certbund-operations.md` captures locale guidance and offline packaging. | +| Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Cccs/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CCCS-02-001 … 02-008 | Observability meter, historical harvest plan, and DOM sanitizer refinements wrapped; ops notes live under `docs/modules/concelier/operations/connectors/cccs.md` with fixtures validating EN/FR list handling. | +| Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.CertBund/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CERTBUND-02-001 … 02-008 | Telemetry/docs (02-006) and history/locale sweep (02-007) completed alongside pipeline; runbook `docs/modules/concelier/operations/connectors/certbund.md` captures locale guidance and offline packaging. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Kisa/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-KISA-02-001 … 02-007 | Connector, tests, and telemetry/docs (02-006) finalized; localisation notes in `docs/dev/kisa_connector_notes.md` complete rollout. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ru.Bdu/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-RUBDU-02-001 … 02-008 | Fetch/parser/mapper refinements, regression fixtures, telemetry/docs, access options, and trusted root packaging all landed; README documents offline access strategy. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ru.Nkcki/TASKS.md | DONE (2025-10-13) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-NKCKI-02-001 … 02-008 | Listing fetch, parser, mapper, fixtures, telemetry/docs, and archive plan finished; Mongo2Go/libcrypto dependency resolved via bundled OpenSSL noted in ops guide. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md | DONE (2025-10-16) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-ICSCISA-02-001 … 02-011 | Feed parser attachment fixes, SemVer exact values, regression suites, telemetry/docs updates, and handover complete; ops runbook now details attachment verification + proxy usage. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Cisco/TASKS.md | DONE (2025-10-14) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-CISCO-02-001 … 02-007 | OAuth fetch pipeline, DTO/mapping, tests, and telemetry/docs shipped; monitoring/export integration follow-ups recorded in Ops docs and exporter backlog (completed). | -| Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Msrc/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-MSRC-02-001 … 02-008 | Azure AD onboarding (02-008) unblocked fetch/parse/map pipeline; fixtures, telemetry/docs, and Offline Kit guidance published in `docs/ops/concelier-msrc-operations.md`. | +| Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Vndr.Msrc/TASKS.md | DONE (2025-10-15) | Team Connector Expansion – Regional & Vendor Feeds | FEEDCONN-MSRC-02-001 … 02-008 | Azure AD onboarding (02-008) unblocked fetch/parse/map pipeline; fixtures, telemetry/docs, and Offline Kit guidance published in `docs/modules/concelier/operations/connectors/msrc.md`. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Cve/TASKS.md | DONE (2025-10-15) | Team Connector Support & Monitoring | FEEDCONN-CVE-02-001 … 02-002 | CVE data-source selection, fetch pipeline, and docs landed 2025-10-10. 2025-10-15: smoke verified using the seeded mirror fallback; connector now logs a warning and pulls from `seed-data/cve/` until live CVE Services credentials arrive. | | Sprint 2 | Connector & Data Implementation Wave | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Kev/TASKS.md | DONE (2025-10-12) | Team Connector Support & Monitoring | FEEDCONN-KEV-02-001 … 02-002 | KEV catalog ingestion, fixtures, telemetry, and schema validation completed 2025-10-12; ops dashboard published. | | Sprint 2 | Connector & Data Implementation Wave | docs/TASKS.md | DONE (2025-10-11) | Team Docs & Knowledge Base | FEEDDOCS-DOCS-01-001 | Canonical schema docs refresh
Updated canonical schema + provenance guides with SemVer style, normalized version rules, decision reason change log, and migration notes. | @@ -97,8 +97,8 @@ Closed sprint tasks archived from SPRINTS.md on 2025-10-19. | Sprint 3 | Conflict Resolution Integration & Communications | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-GHSA-04-002 | GHSA conflict regression fixtures | | Sprint 3 | Conflict Resolution Integration & Communications | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Nvd/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-NVD-04-002 | NVD conflict regression fixtures | | Sprint 3 | Conflict Resolution Integration & Communications | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv/TASKS.md | DONE (2025-10-12) | Team Connector Regression Fixtures | FEEDCONN-OSV-04-002 | OSV conflict regression fixtures
Instructions to work:
Read ./AGENTS.md and module AGENTS. Produce fixture triples supporting the precedence/tie-breaker paths defined in ./src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md and hand them to Merge QA. | -| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-11) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-001 | Concelier Conflict Rules
Runbook published at `docs/ops/concelier-conflict-resolution.md`; metrics/log guidance aligned with Sprint 3 merge counters. | -| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-16) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-002 | Conflict runbook ops rollout
Ops review completed, alert thresholds applied, and change log appended in `docs/ops/concelier-conflict-resolution.md`; task closed after connector signals verified. | +| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-11) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-001 | Concelier Conflict Rules
Runbook published at `docs/modules/concelier/operations/conflict-resolution.md`; metrics/log guidance aligned with Sprint 3 merge counters. | +| Sprint 3 | Conflict Resolution Integration & Communications | docs/TASKS.md | DONE (2025-10-16) | Team Documentation Guild – Conflict Guidance | FEEDDOCS-DOCS-05-002 | Conflict runbook ops rollout
Ops review completed, alert thresholds applied, and change log appended in `docs/modules/concelier/operations/conflict-resolution.md`; task closed after connector signals verified. | | Sprint 4 | Schema Parity & Freshness Alignment | src/Concelier/__Libraries/StellaOps.Concelier.Models/TASKS.md | DONE (2025-10-15) | Team Models & Merge Leads | FEEDMODELS-SCHEMA-04-001 | Advisory schema parity (description/CWE/canonical metric)
Extend `Advisory` and related records with description text, CWE collection, and canonical metric pointer; refresh validation + serializer determinism tests. | | Sprint 4 | Schema Parity & Freshness Alignment | src/Concelier/__Libraries/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-15) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-04-003 | Canonical merger parity for new fields
Teach `CanonicalMerger` to populate description, CWEResults, and canonical metric pointer with provenance + regression coverage. | | Sprint 4 | Schema Parity & Freshness Alignment | src/Concelier/__Libraries/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-15) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-04-004 | Reference normalization & freshness instrumentation cleanup
Implement URL normalization for reference dedupe, align freshness-sensitive instrumentation, and add analytics tests. | @@ -146,7 +146,7 @@ Closed sprint tasks archived from SPRINTS.md on 2025-10-19. | Sprint 7 | Contextual Truth Foundations | src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md | DONE (2025-10-19) | Team Excititor Core & Policy | EXCITITOR-CORE-02-001 | Context signal schema prep – extend consensus models with severity/KEV/EPSS fields and update canonical serializers. | | Sprint 7 | Contextual Truth Foundations | src/Excititor/__Libraries/StellaOps.Excititor.Policy/TASKS.md | DONE (2025-10-19) | Team Excititor Policy | EXCITITOR-POLICY-02-001 | Scoring coefficients & weight ceilings – add α/β options, weight boosts, and validation guidance. | | Sprint 7 | Contextual Truth Foundations | src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md | DONE (2025-10-16) | Team Excititor Attestation | EXCITITOR-ATTEST-01-002 | Rekor v2 client integration – ship transparency log client with retries and offline queue. | -| Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md | DONE (2025-10-18) | Team Scanner Core | SCANNER-CORE-09-501 | Define shared DTOs (ScanJob, ProgressEvent), error taxonomy, and deterministic ID/timestamp helpers aligning with `ARCHITECTURE_SCANNER.md` §3–§4. | +| Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md | DONE (2025-10-18) | Team Scanner Core | SCANNER-CORE-09-501 | Define shared DTOs (ScanJob, ProgressEvent), error taxonomy, and deterministic ID/timestamp helpers aligning with `modules/scanner/architecture.md` §3–§4. | | Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md | DONE (2025-10-18) | Team Scanner Core | SCANNER-CORE-09-502 | Observability helpers (correlation IDs, logging scopes, metric namespacing, deterministic hashes) consumed by WebService/Worker. | | Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md | DONE (2025-10-18) | Team Scanner Core | SCANNER-CORE-09-503 | Security utilities: Authority client factory, OpTok caching, DPoP verifier, restart-time plug-in guardrails for scanner components. | | Sprint 9 | Scanner Build-time | src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md | DONE (2025-10-19) | BuildX Guild | SP9-BLDX-09-001 | Buildx driver scaffold + handshake with Scanner.Emit (local CAS). | @@ -174,7 +174,7 @@ Closed sprint tasks archived from SPRINTS.md on 2025-10-19. | Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Queue/TASKS.md | DONE (2025-10-19) | Team Scanner Queue | SCANNER-QUEUE-09-401 | Queue abstraction + Redis Streams adapter with ack/claim APIs and idempotency tokens. | | Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Queue/TASKS.md | DONE (2025-10-19) | Team Scanner Queue | SCANNER-QUEUE-09-402 | Pluggable backend support (Redis, NATS) with configuration binding, health probes, failover docs. | | Sprint 9 | Scanner Core Foundations | src/Scanner/__Libraries/StellaOps.Scanner.Queue/TASKS.md | DONE (2025-10-19) | Team Scanner Queue | SCANNER-QUEUE-09-403 | Retry + dead-letter strategy with structured logs/metrics for offline deployments. | -| Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance
Team instructions: Read ./AGENTS.md and each module's AGENTS file. Adopt the `NormalizedVersions` array emitted by the models sprint, wiring provenance `decisionReason` where merge overrides occur. Follow ./src/FASTER_MODELING_AND_NORMALIZATION.md; report via src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md (FEEDMERGE-COORD-02-900). Progress 2025-10-11: GHSA/OSV emit normalized arrays with refreshed fixtures; CVE mapper now surfaces SemVer normalized ranges; NVD/KEV adoption pending; outstanding follow-ups include FEEDSTORAGE-DATA-02-001, FEEDMERGE-ENGINE-02-002, and rolling `tools/FixtureUpdater` updates across connectors.
Progress 2025-10-20: Coordination matrix + rollout dashboard refreshed; upcoming deadlines tracked (Cccs/Cisco 2025-10-21, CertBund 2025-10-22, ICS-CISA 2025-10-23, KISA 2025-10-24) with escalation path documented in FEEDMERGE-COORD-02-900.| +| Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa/TASKS.md | DONE (2025-10-12) | Team Connector Normalized Versions Rollout | FEEDCONN-GHSA-02-001 | GHSA normalized versions & provenance
Team instructions: Read ./AGENTS.md and each module's AGENTS file. Adopt the `NormalizedVersions` array emitted by the models sprint, wiring provenance `decisionReason` where merge overrides occur. Follow ./src/FASTER_MODELING_AND_NORMALIZATION.md; report via src/Concelier/__Libraries/StellaOps.Concelier.Merge/TASKS.md (FEEDMERGE-COORD-02-900). Progress 2025-10-11: GHSA/OSV emit normalized arrays with refreshed fixtures; CVE mapper now surfaces SemVer normalized ranges; NVD/KEV adoption pending; outstanding follow-ups include FEEDSTORAGE-DATA-02-001, FEEDMERGE-ENGINE-02-002, and rolling `src/Tools/FixtureUpdater` updates across connectors.
Progress 2025-10-20: Coordination matrix + rollout dashboard refreshed; upcoming deadlines tracked (Cccs/Cisco 2025-10-21, CertBund 2025-10-22, ICS-CISA 2025-10-23, KISA 2025-10-24) with escalation path documented in FEEDMERGE-COORD-02-900.| | Sprint 1 | Stabilize In-Progress Foundations | src/Concelier/StellaOps.Concelier.WebService/TASKS.md | DONE (2025-10-19) | Team WebService & Authority | FEEDWEB-OPS-01-006 | Rename plugin drop directory to namespaced path
Build outputs now point at `StellaOps.Concelier.PluginBinaries`/`StellaOps.Authority.PluginBinaries`; defaults/docs/tests updated to reflect the new layout. | | Sprint 7 | Contextual Truth Foundations | src/Excititor/__Libraries/StellaOps.Excititor.Storage.Mongo/TASKS.md | DONE (2025-10-19) | Team Excititor Storage | EXCITITOR-STORAGE-02-001 | Statement events & scoring signals – immutable VEX statements store, consensus signal fields, and migration `20251019-consensus-signals-statements` with tests (`dotnet test src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/StellaOps.Excititor.Core.Tests.csproj`, `dotnet test src/Excititor/__Tests/StellaOps.Excititor.Storage.Mongo.Tests/StellaOps.Excititor.Storage.Mongo.Tests.csproj`). | | Sprint 7 | Contextual Truth Foundations | src/Concelier/__Libraries/StellaOps.Concelier.Core/TASKS.md | DONE (2025-10-19) | Team Core Engine & Storage Analytics | FEEDCORE-ENGINE-07-001 | Advisory event log & asOf queries – surface immutable statements and replay capability. | diff --git a/docs/implplan/SPRINTS_PRIOR_20251027.md b/docs/implplan/SPRINTS_PRIOR_20251027.md index c32c3696..8f8841c0 100644 --- a/docs/implplan/SPRINTS_PRIOR_20251027.md +++ b/docs/implplan/SPRINTS_PRIOR_20251027.md @@ -40,9 +40,9 @@ This file describe implementation of Stella Ops (docs/README.md). Implementation | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Authority Core | DOCS-POLICY-20-003 | Write `/docs/policy/lifecycle.md` covering workflow + roles. | | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Scheduler Guild | DOCS-POLICY-20-004 | Document policy run modes + cursors in `/docs/policy/runs.md`. | | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Platform Guild | DOCS-POLICY-20-005 | Produce `/docs/api/policy.md` with endpoint schemas + errors. | -| Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, CLI Guild | DOCS-POLICY-20-006 | Author `/docs/cli/policy.md` with commands, exit codes, JSON output. | +| Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, CLI Guild | DOCS-POLICY-20-006 | Author `/docs/modules/cli/guides/policy.md` with commands, exit codes, JSON output. | | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, UI Guild | DOCS-POLICY-20-007 | Create `/docs/ui/policy-editor.md` covering editor, simulation, approvals. | -| Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Architecture Guild | DOCS-POLICY-20-008 | Publish `/docs/architecture/policy-engine.md` with sequence diagrams. | +| Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Architecture Guild | DOCS-POLICY-20-008 | Publish `/docs/modules/policy/architecture.md` with sequence diagrams. | | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Observability Guild | DOCS-POLICY-20-009 | Document metrics/traces/logs in `/docs/observability/policy.md`. | | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Security Guild | DOCS-POLICY-20-010 | Publish `/docs/security/policy-governance.md` for scopes + approvals. | | Sprint 20 | Policy Engine v2 | docs/TASKS.md | DONE (2025-10-26) | Docs Guild, Policy Guild | DOCS-POLICY-20-011 | Add example policies under `/docs/examples/policies/` with commentary. | diff --git a/docs/ingestion/aggregation-only-contract.md b/docs/ingestion/aggregation-only-contract.md index cc79b8e9..3ef8fa0c 100644 --- a/docs/ingestion/aggregation-only-contract.md +++ b/docs/ingestion/aggregation-only-contract.md @@ -1,180 +1,180 @@ -# Aggregation-Only Contract Reference - -> The Aggregation-Only Contract (AOC) is the governing rule set that keeps StellaOps ingestion services deterministic, policy-neutral, and auditable. It applies to Concelier, Excititor, and any future collectors that write raw advisory or VEX documents. - -## 1. Purpose and Scope - -- Defines the canonical behaviour for `advisory_raw` and `vex_raw` collections and the linkset hints they may emit. -- Applies to every ingestion runtime (`StellaOps.Concelier.*`, `StellaOps.Excititor.*`), the Authority scopes that guard them, and the DevOps/QA surfaces that verify compliance. -- Complements the high-level architecture in [Concelier](../ARCHITECTURE_CONCELIER.md) and Authority enforcement documented in [Authority Architecture](../ARCHITECTURE_AUTHORITY.md). -- Paired guidance: see the guard-rail checkpoints in [AOC Guardrails](../aoc/aoc-guardrails.md) and CLI usage that will land in `/docs/cli/` as part of Sprint 19 follow-up. - -## 2. Philosophy and Goals - -- Preserve upstream truth: ingestion only captures immutable raw facts plus provenance, never derived severity or policy decisions. -- Defer interpretation: Policy Engine and downstream overlays remain the sole writers of materialised findings, severity, consensus, or risk scores. -- Make every write explainable: provenance, signatures, and content hashes are required so operators can prove where each fact originated. -- Keep outputs reproducible: identical inputs must yield identical documents, hashes, and linksets across replays and air-gapped installs. - -## 3. Contract Invariants - -| # | Invariant | What it forbids or requires | Enforcement surfaces | -|---|-----------|-----------------------------|----------------------| -| 1 | No derived severity at ingest | Reject top-level keys such as `severity`, `cvss`, `effective_status`, `consensus_provider`, `risk_score`. Raw upstream CVSS remains inside `content.raw`. | Mongo schema validator, `AOCWriteGuard`, Roslyn analyzer, `stella aoc verify`. | -| 2 | No merges or opinionated dedupe | Each upstream document persists on its own; ingestion never collapses multiple vendors into one document. | Repository interceptors, unit/fixture suites. | -| 3 | Provenance is mandatory | `source.*`, `upstream.*`, and `signature` metadata must be present; missing provenance triggers `ERR_AOC_004`. | Schema validator, guard, CLI verifier. | -| 4 | Idempotent upserts | Writes keyed by `(vendor, upstream_id, content_hash)` either no-op or insert a new revision with `supersedes`. Duplicate hashes map to the same document. | Repository guard, storage unique index, CI smoke tests. | -| 5 | Append-only revisions | Updates create a new document with `supersedes` pointer; no in-place mutation of content. | Mongo schema (`supersedes` format), guard, data migration scripts. | -| 6 | Linkset only | Ingestion may compute link hints (`purls`, `cpes`, IDs) to accelerate joins, but must not transform or infer severity or policy. | Linkset builders reviewed via fixtures and analyzers. | -| 7 | Policy-only effective findings | Only Policy Engine identities can write `effective_finding_*`; ingestion callers receive `ERR_AOC_006` if they attempt it. | Authority scopes, Policy Engine guard. | -| 8 | Schema safety | Unknown top-level keys reject with `ERR_AOC_007`; timestamps use ISO 8601 UTC strings; tenant is required. | Mongo validator, JSON schema tests. | -| 9 | Clock discipline | Collectors stamp `fetched_at` and `received_at` monotonically per batch to support reproducibility windows. | Collector contracts, QA fixtures. | - -## 4. Raw Schemas - -### 4.1 `advisory_raw` - -| Field | Type | Notes | -|-------|------|-------| -| `_id` | string | `advisory_raw:{source}:{upstream_id}:{revision}`; deterministic and tenant-scoped. | -| `tenant` | string | Required; injected by Authority middleware and asserted by schema validator. | -| `source.vendor` | string | Provider identifier (e.g., `redhat`, `osv`, `ghsa`). | -| `source.stream` | string | Connector stream name (`csaf`, `osv`, etc.). | -| `source.api` | string | Absolute URI of upstream document; stored for traceability. | -| `source.collector_version` | string | Semantic version of the collector. | -| `upstream.upstream_id` | string | Vendor- or ecosystem-provided identifier (CVE, GHSA, vendor ID). | -| `upstream.document_version` | string | Upstream issued timestamp or revision string. | -| `upstream.fetched_at` / `received_at` | string | ISO 8601 UTC timestamps recorded by the collector. | -| `upstream.content_hash` | string | `sha256:` digest of the raw payload used for idempotency. | -| `upstream.signature` | object | Required structure storing `present`, `format`, `key_id`, `sig`; even unsigned payloads set `present: false`. | -| `content.format` | string | Source format (`CSAF`, `OSV`, etc.). | -| `content.spec_version` | string | Upstream spec version when known. | -| `content.raw` | object | Full upstream payload, untouched except for transport normalisation. | -| `identifiers` | object | Normalised identifiers (`cve`, `ghsa`, `aliases`, etc.) derived losslessly from raw content. | -| `linkset` | object | Join hints (see section 4.3). | -| `supersedes` | string or null | Points to previous revision of same upstream doc when content hash changes. | - -### 4.2 `vex_raw` - -| Field | Type | Notes | -|-------|------|-------| -| `_id` | string | `vex_raw:{source}:{upstream_id}:{revision}`. | -| `tenant` | string | Required; matches advisory collection requirements. | -| `source.*` | object | Same shape and requirements as `advisory_raw`. | -| `upstream.*` | object | Includes `document_version`, timestamps, `content_hash`, and `signature`. | -| `content.format` | string | Typically `CycloneDX-VEX` or `CSAF-VEX`. | -| `content.raw` | object | Entire upstream VEX payload. | -| `identifiers.statements` | array | Normalised statement summaries (IDs, PURLs, status, justification) to accelerate policy joins. | -| `linkset` | object | CVEs, GHSA IDs, and PURLs referenced in the document. | -| `supersedes` | string or null | Same convention as advisory documents. | - -### 4.3 Linkset Fields - -- `purls`: fully qualified Package URLs extracted from raw ranges or product nodes. -- `cpes`: Common Platform Enumerations when upstream docs provide them. -- `aliases`: Any alternate advisory identifiers present in the payload. -- `references`: Array of `{ type, url }` pairs pointing back to vendor advisories, patches, or exploits. -- `reconciled_from`: Provenance of linkset entries (JSON Pointer or field origin) to make automated checks auditable. - -Canonicalisation rules: -- Package URLs are rendered in canonical form without qualifiers/subpaths (`pkg:type/namespace/name@version`). -- CPE values are normalised to the 2.3 binding (`cpe:2.3:part:vendor:product:version:*:*:*:*:*:*:*`). - -### 4.4 `advisory_observations` - -`advisory_observations` is an immutable projection of the validated raw document used by Link‑Not‑Merge overlays. Fields mirror the JSON contract surfaced by `StellaOps.Concelier.Models.Observations.AdvisoryObservation`. - -| Field | Type | Notes | -|-------|------|-------| -| `_id` | string | Deterministic observation id — `{tenant}:{source.vendor}:{upstreamId}:{revision}`. | -| `tenant` | string | Lower-case tenant identifier. | -| `source.vendor` / `source.stream` | string | Connector identity (e.g., `vendor/redhat`, `ecosystem/osv`). | -| `source.api` | string | Absolute URI the connector fetched from. | -| `source.collectorVersion` | string | Optional semantic version of the connector build. | -| `upstream.upstream_id` | string | Advisory identifier as issued by the provider (CVE, vendor ID, etc.). | -| `upstream.document_version` | string | Upstream revision/version string. | -| `upstream.fetchedAt` / `upstream.receivedAt` | datetime | UTC timestamps recorded by the connector. | -| `upstream.contentHash` | string | `sha256:` digest used for idempotency. | -| `upstream.signature` | object | `{present, format?, keyId?, signature?}` describing upstream signature material. | -| `content.format` / `content.specVersion` | string | Raw payload format metadata (CSAF, OSV, JSON, etc.). | -| `content.raw` | object | Full upstream document stored losslessly (Relaxed Extended JSON). | -| `content.metadata` | object | Optional connector-specific metadata (batch ids, hints). | -| `linkset.aliases` | array | Normalized aliases (lower-case, sorted). | -| `linkset.purls` | array | Normalized PURLs extracted from the document. | -| `linkset.cpes` | array | Normalized CPE URIs. | -| `linkset.references` | array | `{ type, url }` pairs (type lower-case). | -| `createdAt` | datetime | Timestamp when Concelier persisted the observation. | -| `attributes` | object | Optional provenance attributes keyed by connector. | - -## 5. Error Model - -| Code | Description | HTTP status | Surfaces | -|------|-------------|-------------|----------| -| `ERR_AOC_001` | Forbidden field detected (severity, cvss, effective data). | 400 | Ingestion APIs, CLI verifier, CI guard. | -| `ERR_AOC_002` | Merge attempt detected (multiple upstream sources fused into one document). | 400 | Ingestion APIs, CLI verifier. | -| `ERR_AOC_003` | Idempotency violation (duplicate without supersedes pointer). | 409 | Repository guard, Mongo unique index, CLI verifier. | -| `ERR_AOC_004` | Missing provenance metadata (`source`, `upstream`, `signature`). | 422 | Schema validator, ingestion endpoints. | -| `ERR_AOC_005` | Signature or checksum mismatch. | 422 | Collector validation, CLI verifier. | -| `ERR_AOC_006` | Attempt to persist derived findings from ingestion context. | 403 | Policy engine guard, Authority scopes. | -| `ERR_AOC_007` | Unknown top-level fields (schema violation). | 400 | Mongo validator, CLI verifier. | - -Consumers should map these codes to CLI exit codes and structured log events so automation can fail fast and produce actionable guidance. - -## 6. API and Tooling Interfaces - -- **Concelier ingestion** (`StellaOps.Concelier.WebService`) - - `POST /ingest/advisory`: accepts upstream payload metadata; server-side guard constructs and persists raw document. - - `GET /advisories/raw/{id}` and filterable list endpoints expose raw documents for debugging and offline analysis. - - `POST /aoc/verify`: runs guard checks over recent documents and returns summary totals plus first violations. -- **Excititor ingestion** (`StellaOps.Excititor.WebService`) mirrors the same surface for VEX documents. -- **CLI workflows** (`stella aoc verify`, `stella sources ingest --dry-run`) surface pre-flight verification; documentation will live in `/docs/cli/` alongside Sprint 19 CLI updates. -- **Authority scopes**: new `advisory:ingest`, `advisory:read`, `vex:ingest`, and `vex:read` scopes enforce least privilege; see [Authority Architecture](../ARCHITECTURE_AUTHORITY.md) for scope grammar. - -## 7. Idempotency and Supersedes Rules - -1. Compute `content_hash` before any transformation; use it with `(source.vendor, upstream.upstream_id)` to detect duplicates. -2. If a document with the same hash already exists, skip the write and log a no-op. -3. When a new hash arrives for an existing upstream document, insert a new record and set `supersedes` to the previous `_id`. -4. Keep supersedes chains acyclic; collectors must resolve conflicts by rewinding before they insert. -5. Expose idempotency counters via metrics (`ingestion_write_total{result=ok|noop}`) to catch regressions early. - -## 8. Migration Playbook - -1. Freeze ingestion writes except for raw pass-through paths while deploying schema validators. -2. Snapshot existing collections to `_backup_*` for rollback safety. -3. Strip forbidden fields from historical documents into a temporary `advisory_view_legacy` used only during transition. -4. Enable Mongo JSON schema validators for `advisory_raw` and `vex_raw`. -5. Run collectors in `--dry-run` to confirm only allowed keys appear; fix violations before lifting the freeze. -6. Point Policy Engine to consume exclusively from raw collections and compute derived outputs downstream. -7. Delete legacy normalisation paths from ingestion code and enable runtime guards plus CI linting. -8. Roll forward CLI, Console, and dashboards so operators can monitor AOC status end-to-end. - -## 9. Observability and Diagnostics - -- **Metrics**: `ingestion_write_total{result=ok|reject}`, `aoc_violation_total{code}`, `ingestion_signature_verified_total{result}`, `ingestion_latency_seconds`, `advisory_revision_count`. -- **Traces**: spans `ingest.fetch`, `ingest.transform`, `ingest.write`, and `aoc.guard` with correlation IDs shared across workers. -- **Logs**: structured entries must include `tenant`, `source.vendor`, `upstream.upstream_id`, `content_hash`, and `violation_code` when applicable. -- **Dashboards**: DevOps should add panels for violation counts, signature failures, supersedes growth, and CLI verifier outcomes for each tenant. - -## 10. Security and Tenancy Checklist - -- Enforce Authority scopes (`advisory:ingest`, `vex:ingest`, `advisory:read`, `vex:read`) and require tenant claims on every request. -- Maintain pinned trust stores for signature verification; capture verification result in metrics and logs. -- Ensure collectors never log secrets or raw authentication headers; redact tokens before persistence. -- Validate that Policy Engine remains the only identity with permission to write `effective_finding_*` documents. -- Verify offline bundles include the raw collections, guard configuration, and verifier binaries so air-gapped installs can audit parity. -- Document operator steps for recovering from violations, including rollback to superseded revisions and re-running policy evaluation. - -## 11. Compliance Checklist - -- [ ] Deterministic guard enabled in Concelier and Excititor repositories. -- [ ] Mongo validators deployed for `advisory_raw` and `vex_raw`. -- [ ] Authority scopes and tenant enforcement verified via integration tests. -- [ ] CLI and CI pipelines run `stella aoc verify` against seeded snapshots. -- [ ] Observability feeds (metrics, logs, traces) wired into dashboards with alerts. -- [ ] Offline kit instructions updated to bundle validators and verifier tooling. -- [ ] Security review recorded covering ingestion, tenancy, and rollback procedures. - ---- - -*Last updated: 2025-10-27 (Sprint 19).* +# Aggregation-Only Contract Reference + +> The Aggregation-Only Contract (AOC) is the governing rule set that keeps StellaOps ingestion services deterministic, policy-neutral, and auditable. It applies to Concelier, Excititor, and any future collectors that write raw advisory or VEX documents. + +## 1. Purpose and Scope + +- Defines the canonical behaviour for `advisory_raw` and `vex_raw` collections and the linkset hints they may emit. +- Applies to every ingestion runtime (`StellaOps.Concelier.*`, `StellaOps.Excititor.*`), the Authority scopes that guard them, and the DevOps/QA surfaces that verify compliance. +- Complements the high-level architecture in [Concelier](../modules/concelier/architecture.md) and Authority enforcement documented in [Authority Architecture](../modules/authority/architecture.md). +- Paired guidance: see the guard-rail checkpoints in [AOC Guardrails](../aoc/aoc-guardrails.md) and CLI usage that will land in `/docs/modules/cli/guides/` as part of Sprint 19 follow-up. + +## 2. Philosophy and Goals + +- Preserve upstream truth: ingestion only captures immutable raw facts plus provenance, never derived severity or policy decisions. +- Defer interpretation: Policy Engine and downstream overlays remain the sole writers of materialised findings, severity, consensus, or risk scores. +- Make every write explainable: provenance, signatures, and content hashes are required so operators can prove where each fact originated. +- Keep outputs reproducible: identical inputs must yield identical documents, hashes, and linksets across replays and air-gapped installs. + +## 3. Contract Invariants + +| # | Invariant | What it forbids or requires | Enforcement surfaces | +|---|-----------|-----------------------------|----------------------| +| 1 | No derived severity at ingest | Reject top-level keys such as `severity`, `cvss`, `effective_status`, `consensus_provider`, `risk_score`. Raw upstream CVSS remains inside `content.raw`. | Mongo schema validator, `AOCWriteGuard`, Roslyn analyzer, `stella aoc verify`. | +| 2 | No merges or opinionated dedupe | Each upstream document persists on its own; ingestion never collapses multiple vendors into one document. | Repository interceptors, unit/fixture suites. | +| 3 | Provenance is mandatory | `source.*`, `upstream.*`, and `signature` metadata must be present; missing provenance triggers `ERR_AOC_004`. | Schema validator, guard, CLI verifier. | +| 4 | Idempotent upserts | Writes keyed by `(vendor, upstream_id, content_hash)` either no-op or insert a new revision with `supersedes`. Duplicate hashes map to the same document. | Repository guard, storage unique index, CI smoke tests. | +| 5 | Append-only revisions | Updates create a new document with `supersedes` pointer; no in-place mutation of content. | Mongo schema (`supersedes` format), guard, data migration scripts. | +| 6 | Linkset only | Ingestion may compute link hints (`purls`, `cpes`, IDs) to accelerate joins, but must not transform or infer severity or policy. | Linkset builders reviewed via fixtures and analyzers. | +| 7 | Policy-only effective findings | Only Policy Engine identities can write `effective_finding_*`; ingestion callers receive `ERR_AOC_006` if they attempt it. | Authority scopes, Policy Engine guard. | +| 8 | Schema safety | Unknown top-level keys reject with `ERR_AOC_007`; timestamps use ISO 8601 UTC strings; tenant is required. | Mongo validator, JSON schema tests. | +| 9 | Clock discipline | Collectors stamp `fetched_at` and `received_at` monotonically per batch to support reproducibility windows. | Collector contracts, QA fixtures. | + +## 4. Raw Schemas + +### 4.1 `advisory_raw` + +| Field | Type | Notes | +|-------|------|-------| +| `_id` | string | `advisory_raw:{source}:{upstream_id}:{revision}`; deterministic and tenant-scoped. | +| `tenant` | string | Required; injected by Authority middleware and asserted by schema validator. | +| `source.vendor` | string | Provider identifier (e.g., `redhat`, `osv`, `ghsa`). | +| `source.stream` | string | Connector stream name (`csaf`, `osv`, etc.). | +| `source.api` | string | Absolute URI of upstream document; stored for traceability. | +| `source.collector_version` | string | Semantic version of the collector. | +| `upstream.upstream_id` | string | Vendor- or ecosystem-provided identifier (CVE, GHSA, vendor ID). | +| `upstream.document_version` | string | Upstream issued timestamp or revision string. | +| `upstream.fetched_at` / `received_at` | string | ISO 8601 UTC timestamps recorded by the collector. | +| `upstream.content_hash` | string | `sha256:` digest of the raw payload used for idempotency. | +| `upstream.signature` | object | Required structure storing `present`, `format`, `key_id`, `sig`; even unsigned payloads set `present: false`. | +| `content.format` | string | Source format (`CSAF`, `OSV`, etc.). | +| `content.spec_version` | string | Upstream spec version when known. | +| `content.raw` | object | Full upstream payload, untouched except for transport normalisation. | +| `identifiers` | object | Normalised identifiers (`cve`, `ghsa`, `aliases`, etc.) derived losslessly from raw content. | +| `linkset` | object | Join hints (see section 4.3). | +| `supersedes` | string or null | Points to previous revision of same upstream doc when content hash changes. | + +### 4.2 `vex_raw` + +| Field | Type | Notes | +|-------|------|-------| +| `_id` | string | `vex_raw:{source}:{upstream_id}:{revision}`. | +| `tenant` | string | Required; matches advisory collection requirements. | +| `source.*` | object | Same shape and requirements as `advisory_raw`. | +| `upstream.*` | object | Includes `document_version`, timestamps, `content_hash`, and `signature`. | +| `content.format` | string | Typically `CycloneDX-VEX` or `CSAF-VEX`. | +| `content.raw` | object | Entire upstream VEX payload. | +| `identifiers.statements` | array | Normalised statement summaries (IDs, PURLs, status, justification) to accelerate policy joins. | +| `linkset` | object | CVEs, GHSA IDs, and PURLs referenced in the document. | +| `supersedes` | string or null | Same convention as advisory documents. | + +### 4.3 Linkset Fields + +- `purls`: fully qualified Package URLs extracted from raw ranges or product nodes. +- `cpes`: Common Platform Enumerations when upstream docs provide them. +- `aliases`: Any alternate advisory identifiers present in the payload. +- `references`: Array of `{ type, url }` pairs pointing back to vendor advisories, patches, or exploits. +- `reconciled_from`: Provenance of linkset entries (JSON Pointer or field origin) to make automated checks auditable. + +Canonicalisation rules: +- Package URLs are rendered in canonical form without qualifiers/subpaths (`pkg:type/namespace/name@version`). +- CPE values are normalised to the 2.3 binding (`cpe:2.3:part:vendor:product:version:*:*:*:*:*:*:*`). + +### 4.4 `advisory_observations` + +`advisory_observations` is an immutable projection of the validated raw document used by Link‑Not‑Merge overlays. Fields mirror the JSON contract surfaced by `StellaOps.Concelier.Models.Observations.AdvisoryObservation`. + +| Field | Type | Notes | +|-------|------|-------| +| `_id` | string | Deterministic observation id — `{tenant}:{source.vendor}:{upstreamId}:{revision}`. | +| `tenant` | string | Lower-case tenant identifier. | +| `source.vendor` / `source.stream` | string | Connector identity (e.g., `vendor/redhat`, `ecosystem/osv`). | +| `source.api` | string | Absolute URI the connector fetched from. | +| `source.collectorVersion` | string | Optional semantic version of the connector build. | +| `upstream.upstream_id` | string | Advisory identifier as issued by the provider (CVE, vendor ID, etc.). | +| `upstream.document_version` | string | Upstream revision/version string. | +| `upstream.fetchedAt` / `upstream.receivedAt` | datetime | UTC timestamps recorded by the connector. | +| `upstream.contentHash` | string | `sha256:` digest used for idempotency. | +| `upstream.signature` | object | `{present, format?, keyId?, signature?}` describing upstream signature material. | +| `content.format` / `content.specVersion` | string | Raw payload format metadata (CSAF, OSV, JSON, etc.). | +| `content.raw` | object | Full upstream document stored losslessly (Relaxed Extended JSON). | +| `content.metadata` | object | Optional connector-specific metadata (batch ids, hints). | +| `linkset.aliases` | array | Normalized aliases (lower-case, sorted). | +| `linkset.purls` | array | Normalized PURLs extracted from the document. | +| `linkset.cpes` | array | Normalized CPE URIs. | +| `linkset.references` | array | `{ type, url }` pairs (type lower-case). | +| `createdAt` | datetime | Timestamp when Concelier persisted the observation. | +| `attributes` | object | Optional provenance attributes keyed by connector. | + +## 5. Error Model + +| Code | Description | HTTP status | Surfaces | +|------|-------------|-------------|----------| +| `ERR_AOC_001` | Forbidden field detected (severity, cvss, effective data). | 400 | Ingestion APIs, CLI verifier, CI guard. | +| `ERR_AOC_002` | Merge attempt detected (multiple upstream sources fused into one document). | 400 | Ingestion APIs, CLI verifier. | +| `ERR_AOC_003` | Idempotency violation (duplicate without supersedes pointer). | 409 | Repository guard, Mongo unique index, CLI verifier. | +| `ERR_AOC_004` | Missing provenance metadata (`source`, `upstream`, `signature`). | 422 | Schema validator, ingestion endpoints. | +| `ERR_AOC_005` | Signature or checksum mismatch. | 422 | Collector validation, CLI verifier. | +| `ERR_AOC_006` | Attempt to persist derived findings from ingestion context. | 403 | Policy engine guard, Authority scopes. | +| `ERR_AOC_007` | Unknown top-level fields (schema violation). | 400 | Mongo validator, CLI verifier. | + +Consumers should map these codes to CLI exit codes and structured log events so automation can fail fast and produce actionable guidance. + +## 6. API and Tooling Interfaces + +- **Concelier ingestion** (`StellaOps.Concelier.WebService`) + - `POST /ingest/advisory`: accepts upstream payload metadata; server-side guard constructs and persists raw document. + - `GET /advisories/raw/{id}` and filterable list endpoints expose raw documents for debugging and offline analysis. + - `POST /aoc/verify`: runs guard checks over recent documents and returns summary totals plus first violations. +- **Excititor ingestion** (`StellaOps.Excititor.WebService`) mirrors the same surface for VEX documents. +- **CLI workflows** (`stella aoc verify`, `stella sources ingest --dry-run`) surface pre-flight verification; documentation will live in `/docs/modules/cli/guides/` alongside Sprint 19 CLI updates. +- **Authority scopes**: new `advisory:ingest`, `advisory:read`, `vex:ingest`, and `vex:read` scopes enforce least privilege; see [Authority Architecture](../modules/authority/architecture.md) for scope grammar. + +## 7. Idempotency and Supersedes Rules + +1. Compute `content_hash` before any transformation; use it with `(source.vendor, upstream.upstream_id)` to detect duplicates. +2. If a document with the same hash already exists, skip the write and log a no-op. +3. When a new hash arrives for an existing upstream document, insert a new record and set `supersedes` to the previous `_id`. +4. Keep supersedes chains acyclic; collectors must resolve conflicts by rewinding before they insert. +5. Expose idempotency counters via metrics (`ingestion_write_total{result=ok|noop}`) to catch regressions early. + +## 8. Migration Playbook + +1. Freeze ingestion writes except for raw pass-through paths while deploying schema validators. +2. Snapshot existing collections to `_backup_*` for rollback safety. +3. Strip forbidden fields from historical documents into a temporary `advisory_view_legacy` used only during transition. +4. Enable Mongo JSON schema validators for `advisory_raw` and `vex_raw`. +5. Run collectors in `--dry-run` to confirm only allowed keys appear; fix violations before lifting the freeze. +6. Point Policy Engine to consume exclusively from raw collections and compute derived outputs downstream. +7. Delete legacy normalisation paths from ingestion code and enable runtime guards plus CI linting. +8. Roll forward CLI, Console, and dashboards so operators can monitor AOC status end-to-end. + +## 9. Observability and Diagnostics + +- **Metrics**: `ingestion_write_total{result=ok|reject}`, `aoc_violation_total{code}`, `ingestion_signature_verified_total{result}`, `ingestion_latency_seconds`, `advisory_revision_count`. +- **Traces**: spans `ingest.fetch`, `ingest.transform`, `ingest.write`, and `aoc.guard` with correlation IDs shared across workers. +- **Logs**: structured entries must include `tenant`, `source.vendor`, `upstream.upstream_id`, `content_hash`, and `violation_code` when applicable. +- **Dashboards**: DevOps should add panels for violation counts, signature failures, supersedes growth, and CLI verifier outcomes for each tenant. + +## 10. Security and Tenancy Checklist + +- Enforce Authority scopes (`advisory:ingest`, `vex:ingest`, `advisory:read`, `vex:read`) and require tenant claims on every request. +- Maintain pinned trust stores for signature verification; capture verification result in metrics and logs. +- Ensure collectors never log secrets or raw authentication headers; redact tokens before persistence. +- Validate that Policy Engine remains the only identity with permission to write `effective_finding_*` documents. +- Verify offline bundles include the raw collections, guard configuration, and verifier binaries so air-gapped installs can audit parity. +- Document operator steps for recovering from violations, including rollback to superseded revisions and re-running policy evaluation. + +## 11. Compliance Checklist + +- [ ] Deterministic guard enabled in Concelier and Excititor repositories. +- [ ] Mongo validators deployed for `advisory_raw` and `vex_raw`. +- [ ] Authority scopes and tenant enforcement verified via integration tests. +- [ ] CLI and CI pipelines run `stella aoc verify` against seeded snapshots. +- [ ] Observability feeds (metrics, logs, traces) wired into dashboards with alerts. +- [ ] Offline kit instructions updated to bundle validators and verifier tooling. +- [ ] Security review recorded covering ingestion, tenancy, and rollback procedures. + +--- + +*Last updated: 2025-10-27 (Sprint 19).* diff --git a/docs/moat.md b/docs/moat.md new file mode 100644 index 00000000..01fc91b4 --- /dev/null +++ b/docs/moat.md @@ -0,0 +1,430 @@ +# StellaOps Moat Track — Spec Outline v0.3 + +**Scope of this doc:** +(1) Deterministic Replayable Scans (SRM), (2) Policy Engine & Lattice UI, (3) Sovereign Readiness (CryptoProfile + RootPack), (4) Attestation Observability Graph (AOG), (5) Procurement‑Grade Trust Statement, (6) Third‑Party Proof Channel, (7) Zastava differential SBOM + AI scheduler. + +Cross‑cutting principles: offline‑first, cryptographic determinism, evidence‑bound decisions, regional crypto compliance, minimal operational friction. + +--- + +## 0) Shared Concepts (applies to all 7) + +* **Artifact identity:** digest-first (OCI image digest, file sha256). +* **Canonicalization:** all structured payloads (SBOM, SRM, Trust Statement JSON, VEX) are normalized via Canonical JSON (RFC‑8785‑like) prior to hashing/signing. +* **Signatures:** DSSE envelopes; **dual‑signing** supported (e.g., FIPS ECDSA + GOST R 34.10; or ECDSA + SM2). +* **Attestation chain:** each decision (scan, VEX merge, policy evaluation) yields a signed, replayable record. +* **Profiles & Packs:** **CryptoProfile** (algorithm + root policy) and **RootPack** (trust anchors + OCSP/CRL/TSA mirrors) are versioned and importable. +* **Policy Unit Tests:** any policy/lattice bundle ships with fixtures expected to pass during CI. + +--- + +## 1) Deterministic Replayable Scans — SRM + +### Objective + +Make every scan a **provable, re‑executable fact**. Auditors can replay; results are bit‑for‑bit reproducible. + +### Deliverables + +* **SRM v0.1** schema (YAML/JSON) +* Deterministic executor + `stella replay` +* Replay diffing and result hashing + +### SRM (Stella Replay Manifest) — schema (abridged) + +```yaml +apiVersion: srm.stellaops.dev/v0.1 +scan: + id: uuid + timestamp: ISO8601 + engine: { name: "stella-scan", version: "1.7.3", build_sha: "" } +environment: + os_image: + kernel: { uname: "...", cgroups: "v2" } + cpu_features: [avx2, sse4.2] +inputs: + image: { name: "reg/app:1.9.2", digest: "", layers: ["", ...] } + sbom: { type: "cyclonedx@1.5", digest: "" } + vex_set: [{ type: "openvex", digest: "" }] + lattice_policy: { id: "corp-policy@2025-08-15", digest: "" } +rules_and_feeds: + rulesets: [{ name: "vuln-core", version: "2025.08.30", digest: "" }] + feeds: + - { name: "nvd", snapshot_date: "2025-08-30", archive_digest: "" } +execution: + mode: deterministic + random_seed: 314159 + ordering: lexical + heuristics: { binary_scan: true, secrets: false } +evidence: + files_hashed: 12873 + samples: [{ path: "/usr/lib/libssl.so.3", sha256: "" }] +outputs: + report_digest: "" # canonical JSON root hash + artifacts: + - { name: "findings.json", sha256: "" } +signatures: + - { scheme: "DSSE", CryptoProfile: "FIPS-140-3", signer: "build-ca@corp" } + - { scheme: "DSSE", CryptoProfile: "GOST-2012", signer: "ru-ca@corp" } +rekor: { entries: ["", ...] } # optional (offline allowed) +``` + +### CLI & API + +* `stella scan --image reg/app@sha256:... --srm-out srm.yaml --findings findings.json` +* `stella replay srm.yaml --out replay.json --assert-digest ` +* `POST /v1/srm/replay` → returns `ok`, `replay_report_digest`, `diff` (if any). + +### Determinism Rules + +* Single thread or ordered parallel with stable scheduling; sorted inputs; fixed random seed; pinned rules/feeds/policies from SRM; identical canonicalization routines. + +### Acceptance Criteria + +* Replaying SRM on a different host returns identical `report_digest`. +* If any feed archive differs by 1 bit, replay fails with a precise diff. +* SRM size ≤ 25 MB for a typical microservice image (excludes large feed archives, which may be referenced by digest and bundled as a side‑car tar). + +--- + +## 2) Policy Engine & Lattice UI + +### Objective + +Turn VEX merging and severity logic into **programmable, testable algebra** with explainability. + +### Model + +* **Domain:** partial order over vulnerability states: + `unknown < under_investigation < affected || not_affected < fixed`. + Cross‑product with *scope*: `{runtime_path, build_path, optional_path}` and *confidence*: `{low, med, high}`. +* **Merge semantics:** monotonic lattice joins; conflict resolution rules prioritized by signed source trust and policy precedence. + +### DSL (sketch) + +```hocon +policy "corp-runtime" version "2025.08.15" { + sources { + trust_order = ["vendor:redhat", "internal:appsec", "public:nvd"] + require_signatures = true + } + + rules { + when vex.statement == "not_affected" + and evidence.entrypoint_exposes == false + then state := not_affected with confidence := high; + + when package.is_dev_dependency == true + then scope := optional_path; + + when cvss >= 9.0 and reachable == true + then priority := "block"; + } + + guards { + forbid unsigned_sources; + forbid downgrade_of_state_below previous_state; + } +} +``` + +### UI (“Trust Algebra Studio”) + +* Drag‑and‑drop rule blocks, precedence editor, **simulation mode** on sample SBOM/VEX; **policy unit tests**. +* Export **signed** `.lattice.json`; importable into CI. + +### CLI & API + +* `stella policy lint corp-runtime.lattice.json` +* `stella policy test --fixtures fixtures/` +* `POST /v1/policy/evaluate` → normalized decision + proof trail. + +### Acceptance Criteria + +* Given same inputs, policy evaluation yields identical decision + proof trail hash. +* UI can round‑trip DSL ⇄ JSON with no semantic drift. +* Policy pack signature required to run in “enforced” mode. + +--- + +## 3) Sovereign Readiness — CryptoProfile + RootPack + +### Objective + +**Drop‑in regional cryptography** (Russia/China/EU/US) with offline operation. + +### CryptoProfile (attached to every signature/attestation) + +```json +{ + "id": "GOST-2012@v1", + "algorithms": {"sign":"GOST R 34.10-2012","hash":"GOST R 34.11-2012","cipher":"GOST 34.12-2015"}, + "key_policy": {"curve":"id-tc26-gost-3410-2012-256","hsm_required": true}, + "time_stamping": {"tsa": "rootpack://ru/tsa1"}, + "roots": ["rootpack://ru/trustanchors/gost-ca1"] +} +``` + +### RootPack + +* Tarball containing: trust anchors, intermediate CAs, OCSP/CRL snapshots, TSA profiles, policy constraints (e.g., no cross‑sign with foreign roots), and region metadata. +* Installed via: `stella rootpack import rootpack_ru_v1.tar.gz`. + +### Dual‑Signing & Guardrails + +* Policy flags like `allow_dual_signing FIPS+GOST`, `forbid_sm2_for_us_exports` (example only). +* Enforcement happens at signing time and verification time. + +### Acceptance Criteria + +* Offline verification using RootPack succeeds; online OCSP disabled per policy. +* Mis‑profiled signatures are rejected with explicit reason codes. +* Dual‑signed DSSE verifies under both profiles when allowed. + +--- + +## 4) Attestation Observability Graph (AOG) + +### Objective + +Make trust **observable**. Expose SLIs/SLOs for cryptographic posture & policy compliance. + +### Data Model + +* Nodes: `{artifact, sbom, policy, vex, srm, signature, rootpack, runtime_instance}` +* Edges: `derived_from`, `signed_by`, `evaluated_by`, `replayed_by`, `runs_as` + +### Metrics (OpenTelemetry/Prometheus) + +* `stella_trust_sli{service,env}` = fraction of running pods whose image has a valid SRM‑backed attestation chain under the active policy. +* `stella_attestation_latency_seconds` (P50/P95) from build to verified‑ready. +* `stella_policy_drift_events_total` (increment when running policy != signed policy). +* `stella_exception_without_proof_total` (must be 0). +* `stella_replay_success_ratio` (per week). + +**SLO Example** + +* **Trust SLO ≥ 99.9%** measured hourly; error budget resets monthly. + +### Interfaces + +* `stella aog export --format otlp` +* `GET /v1/aog/graph?artifactDigest=...` → subgraph JSON (with signed edge proofs). +* Grafana dashboards (packaged). + +### Acceptance Criteria + +* AOG can reconstruct the full trust lineage for any running pod in ≤ 2s (p95) on a 1k‑service cluster. +* Metrics cardinality bounded (service/env/policy only). + +--- + +## 5) Procurement‑Grade “Trust Statement” + +### Objective + +One **board‑ready** artifact that unifies security posture across vendors; machine‑readable twin for ERP/GRC. + +### Outputs + +* **PDF** (human): signed, watermark, controlled fields for vendor name/version/date, summary graphs, SLOs, exceptions with PCE (proof‑carrying exceptions). +* **JSON** (machine): normalized schema below; DSSE‑signed; includes SRM and policy references. + +```json +{ + "schema": "trust-statement.stellaops.dev/v1", + "vendor": {"name": "Acme","product":"Payments API","version":"1.9.2"}, + "build": {"image_digest":"sha256:...","srm_digest":"sha256:..."}, + "policy": {"id":"corp-runtime@2025-08-15","digest":"sha256:..."}, + "summary": { + "trust_sli": 0.9992, + "exceptions": 1, + "open_findings": {"critical":0,"high":2,"medium":4,"low":12} + }, + "exceptions": [{ + "id":"EXC-2025-0912", + "reason":"not_affected-via-vex", + "proof_digest":"sha256:...", + "expiry":"2026-01-15" + }], + "signatures": [{ "CryptoProfile":"FIPS-140-3" }] +} +``` + +### Integrations + +* Push connectors: **SAP Ariba, ServiceNow, Archer, Jira** (webhooks or SFTP in offline flows). +* CLI: `stella trust-statement generate --srm srm.yaml --policy corp-runtime.lattice.json --out acme-1.9.2.trust.json --pdf`. + +### Acceptance Criteria + +* JSON validates against schema; PDF and JSON hashes match the DSSE statement. +* ERP ingest POC: Ariba/ServiceNow field mapping validated. + +--- + +## 6) Third‑Party Proof Channel + +### Objective + +Create a **publisher ecosystem** for upstream proofs: SBOM, VEX, and **VDR (Vulnerability Derivation Reason)**. + +### Publisher Model + +* **Identity:** publishers obtain a **Publisher Certificate** (could be verified via RootPack‑anchored CA or cross‑signed). +* **Submission:** `stella ledger publish --type {sbom|vex|vdr} --artifact --file proof.json --sign`. +* **Moderation & Revocation:** CRL‑like **Proof Revocation List (PRL)** with signed reasons. + +### VDR (schema sketch) + +```json +{ + "schema":"vdr.stellaops.dev/v1", + "artifact":"sha256:...", + "cve":"CVE-2025-12345", + "claim":"not_affected", + "method":"entrypoint_unreachable|abi_mismatch|dead_code", + "evidence_refs":[{"type":"symbol_map","digest":"sha256:..."}], + "publisher":"redhat://rhel", + "signatures":[...] +} +``` + +### Consumption + +* Policies can **prioritize** publisher channels by trust level. +* AOG shows which proofs originated from which publishers. + +### Acceptance Criteria + +* At least one upstream (e.g., base image vendor) can publish and your policy can consume & rank it. +* PRL revokes a proof and AOG reflects the change within 5 minutes. + +--- + +## 7) Zastava — differential SBOM + AI enrichment scheduler + +### Objective + +Produce **entrypoint‑aware differential SBOMs** and continually **re‑enrich** new/old SBOMs with AI context and exposure‑aware prioritization. + +### Concepts + +* **dSBOM:** SBOM that reflects effective dependency set for a specific `ENTRYPOINT/CMD` and runtime flags (e.g., `--server.urls`, `DOTNET_...`). +* **Scheduler:** rescans **old SBOMs** when: (a) new CVE feeds arrive, (b) new VEX/VDR appear, (c) policy changes, or (d) AI models learn new exploitability signals. + +### Pipeline + +1. **Static slice:** infer reachable packages from entrypoint (e.g., `.NET Kestrel` vs CLI tool). +2. **Runtime slice (optional):** collect process tree, open sockets, and imported modules at startup in a **shadow run** or mirrored traffic. +3. **Diff:** `dSBOM = SBOM ∩ (static_reachable ∪ runtime_observed)`. +4. **AI Enrichment:** Zastava annotates each finding with *context weights* (exposed/not exposed, network scope, RBAC, secrets proximity). +5. **Plan:** produce PRs (Dockerfile base bump, package pin, k8s Service change). +6. **Scheduler:** + + * `stella zastava schedule --query 'service=payments AND env=prod' --interval 6h` + * Triggers re‑evaluation and emits updated SRM + Trust deltas. + +### dSBOM format (addon) + +```json +{ + "schema":"cyclonedx+stella-diff@1.0", + "base_sbom":"sha256:...", + "entrypoint": ["/app/bin/Release/net8.0/app.dll"], + "cmd": ["--urls","http://127.0.0.1:8080"], + "static_reachable": ["pkg:nuget/Kestrel@*", "pkg:nuget/System.Data@*"], + "runtime_observed": ["pkg:rpm/openssl@3.0.9"], + "excluded_paths": ["/usr/share/docs/**"], + "digest":"sha256:..." +} +``` + +### Kestrel example (priority logic) + +* If Kestrel present but Service is `ClusterIP` and no Ingress, **deprioritize**; if `LoadBalancer`/`NodePort` with 0‑RTT TLS disabled, **prioritize**. +* Zastava produces an **explainable card**: “Priority lowered due to non‑exposed runtime path; evidence: `kubectl get svc`, `netstat`, policy rule #42.” + +### Acceptance Criteria + +* Changing `ENTRYPOINT` produces a different, signed dSBOM and updated priorities. +* Scheduler updates stale SBOMs and issues signed deltas without network access (when RootPacks + feed mirrors are available). + +--- + +## Cross‑Cutting Security & Compliance + +* **Sanctions & Guardrails:** per‑profile constraints (e.g., forbid dual‑signing across certain jurisdictions). Policy‑enforced at sign/verify time. +* **HSM Integrations:** PKCS#11 providers for each profile (FIPS, GOST, SM2). +* **Data handling:** SRMs and Trust Statements may contain paths and hashes; optional redaction profiles for vendor sharing. + +--- + +## Interfaces Summary (CLI) + +```bash +# Scans / Replay +stella scan --image --srm-out srm.yaml +stella replay srm.yaml --assert-digest + +# Policy & Lattice +stella policy lint corp.lattice.json +stella policy test --fixtures fixtures/ +stella policy sign --profile FIPS-140-3 + +# Crypto Sovereign +stella rootpack import rootpack_ru_v1.tar.gz +stella attest sign --profile GOST-2012 --in srm.yaml +stella attest verify --profiles GOST-2012,FIPS-140-3 + +# AOG +stella aog export --format otlp +stella aog graph --artifact + +# Trust Statement +stella trust-statement generate --srm srm.yaml --policy corp.lattice.json --pdf out.pdf --json out.json + +# Third-Party Proof Channel +stella ledger publish --type vdr --artifact --file vdr.json --sign +stella ledger revoke --id --reason "superseded" + +# Zastava +stella zastava diff-sbom --image --entrypoint "" --out dsbom.json +stella zastava enrich --sbom dsbom.json --findings findings.json +stella zastava schedule --query 'env=prod' --interval 6h +``` + +--- + +## Success Metrics (per pillar) + +* **SRM:** ≥ 99% of production images have SRM attached; **Replay Success Ratio** ≥ 0.99 weekly. +* **Policy/Lattice:** 100% of exceptions carry proof; policy test coverage ≥ 90% on top CVE classes. +* **Sovereign:** RootPacks for RU/CN/EU/US verified; dual‑signing working in CI; offline verification median < 200 ms. +* **AOG:** Trust SLO ≥ 99.9%; lineage lookup p95 ≤ 2s. +* **Trust Statement:** Accepted by at least one ERP (pilot); generation time ≤ 15s. +* **Third‑Party Channel:** ≥ 3 upstream publishers integrated; PRL revocations flow to AOG within 5 minutes. +* **Zastava:** dSBOM reduces non‑reachable high/critical findings by ≥ 35% without raising exposure incidents. + +--- + +## Risks & Mitigations + +* **Crypto complexity:** profile misuse → strict guardrails + default safe profiles, strong linting. +* **Cardinality/telemetry blow‑ups:** AOG label hygiene + sampling. +* **Vendor adoption (Proof Channel):** seed with your own base images and internal frameworks; provide SDKs and reference publishers. +* **Determinism regressions:** CI runs replay tests on golden SRMs; any drift fails the build. + +--- + +## 90‑Day Moat‑First Milestones + +1. **SRM v0.1**: schema, deterministic executor, CLI replay, golden tests. +2. **Policy Engine MVP**: DSL + evaluator + UI simulation; policy unit tests; signed policy packs. +3. **CryptoProfile/RootPack MVP**: FIPS + GOST working; dual‑signing; offline verify. +4. **AOG MVP**: lineage service + OTLP exporter + Grafana pack; Trust SLI. +5. **Trust Statement MVP**: JSON + PDF; ServiceNow ingest POC. +6. **Proof Channel alpha**: publisher identity + VDR schema + local ledger; PRL. +7. **Zastava α**: `diff-sbom` + exposure heuristics for `.NET Kestrel`; scheduler with offline mirrors. + +--- diff --git a/docs/modules/advisory-ai/AGENTS.md b/docs/modules/advisory-ai/AGENTS.md new file mode 100644 index 00000000..dcece288 --- /dev/null +++ b/docs/modules/advisory-ai/AGENTS.md @@ -0,0 +1,22 @@ +# Advisory AI agent guide + +## Mission +Advisory AI is the retrieval-augmented assistant that synthesizes advisory and VEX evidence into operator-ready summaries, conflict explanations, and remediation plans with strict provenance. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Review ./architecture.md for retrieval pipeline, guardrails, and profile support. +2. Open ../../implplan/SPRINTS.md and locate stories for this component. +3. Check ./TASKS.md and update status before/after work. +4. Read README/architecture for design context and update as the implementation evolves. + +## Guardrails +- Uphold Aggregation-Only Contract boundaries when consuming ingestion data. +- Preserve determinism and provenance in all derived outputs. +- Document offline/air-gap pathways for any new feature. +- Update telemetry/observability assets alongside feature work. diff --git a/docs/modules/advisory-ai/README.md b/docs/modules/advisory-ai/README.md new file mode 100644 index 00000000..c4b3dcda --- /dev/null +++ b/docs/modules/advisory-ai/README.md @@ -0,0 +1,29 @@ +# StellaOps Advisory AI + +Advisory AI is the retrieval-augmented assistant that synthesizes advisory and VEX evidence into operator-ready summaries, conflict explanations, and remediation plans with strict provenance. + +## Responsibilities +- Generate policy-aware advisory summaries with citations back to Conseiller and Excititor evidence. +- Explain conflicting advisories/VEX statements using weights from VEX Lens and Policy Engine. +- Propose remediation hints aligned with Offline Kit staging and export bundles. +- Expose API/UI surfaces with guardrails on model prompts, outputs, and retention. + +## Key components +- RAG pipeline drawing from Conseiller, Excititor, VEX Lens, Policy Engine, and SBOM Service data. +- Prompt templates and guard models enforcing provenance and redaction policies. +- Vercel/offline inference workers with deterministic caching of generated artefacts. + +## Integrations & dependencies +- Authority for tenant-aware access control. +- Policy Engine for context-specific decisions and explain traces. +- Console/CLI for interaction surfaces. +- Export Center/Vuln Explorer for embedding generated briefs. + +## Operational notes +- Model cache management and offline bundle packaging per Epic 8 requirements. +- Usage/latency dashboards for prompt/response monitoring. +- Redaction policies validated against security/LLM guardrail tests. + +## Epic alignment +- Epic 8: Advisory AI Assistant. +- DOCS-AI stories to be tracked in ../../TASKS.md. diff --git a/docs/modules/advisory-ai/TASKS.md b/docs/modules/advisory-ai/TASKS.md new file mode 100644 index 00000000..e3873e52 --- /dev/null +++ b/docs/modules/advisory-ai/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Advisory AI + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| ADVISORY-AI-DOCS-0001 | TODO | Docs Guild | Ensure ./README.md reflects the latest epic deliverables. | Align with ./AGENTS.md | +| ADVISORY-AI-ENG-0001 | TODO | Module Team | Break down epic milestones into actionable stories. | Sync into ../../TASKS.md | +| ADVISORY-AI-OPS-0001 | TODO | Ops Guild | Prepare runbooks/observability assets once MVP lands. | Document outputs in ./README.md | diff --git a/docs/modules/advisory-ai/architecture.md b/docs/modules/advisory-ai/architecture.md new file mode 100644 index 00000000..bbaf1d94 --- /dev/null +++ b/docs/modules/advisory-ai/architecture.md @@ -0,0 +1,100 @@ +# Advisory AI architecture + +> Captures the retrieval, guardrail, and inference packaging requirements defined in the Advisory AI implementation plan and related module guides. + +## 1) Goals + +- Summarise advisories/VEX evidence into operator-ready briefs with citations. +- Explain conflicting statements with provenance and trust weights (using VEX Lens & Excititor data). +- Suggest remediation plans aligned with Offline Kit deployment models and scheduler follow-ups. +- Operate deterministically where possible; cache generated artefacts with digests for audit. + +## 2) Pipeline overview + +``` + +---------------------+ + Concelier/VEX Lens | Evidence Retriever | + Policy Engine ----> | (vector + keyword) | ---> Context Pack (JSON) + Zastava runtime +---------------------+ + | + v + +-------------+ + | Prompt | + | Assembler | + +-------------+ + | + v + +-------------+ + | Guarded LLM | + | (local/host)| + +-------------+ + | + v + +-----------------+ + | Citation & | + | Validation | + +-----------------+ + | + v + +----------------+ + | Output cache | + | (hash, bundle) | + +----------------+ +``` + +## 3) Retrieval & context + +- Hybrid search: vector embeddings (SBERT-compatible) + keyword filters for advisory IDs, PURLs, CVEs. +- Context packs include: + - Advisory raw excerpts with highlighted sections and source URLs. + - VEX statements (normalized tuples + trust metadata). + - Policy explain traces for the affected finding. + - Runtime/impact hints from Zastava (exposure, entrypoints). + - Export-ready remediation data (fixed versions, patches). + +All context references include `content_hash` and `source_id` enabling verifiable citations. + +## 4) Guardrails + +- Prompt templates enforce structure: summary, conflicts, remediation, references. +- Response validator ensures: + - No hallucinated advisories (every fact must map to input context). + - Citations follow `[n]` indexing referencing actual sources. + - Remediation suggestions only cite policy-approved sources (fixed versions, vendor hotfixes). +- Moderation/PII filters prevent leaking secrets; responses failing validation are rejected and logged. + +## 5) Output persistence + +- Cached artefacts stored in `advisory_ai_outputs` with fields: + - `output_hash` (sha256 of JSON response). + - `input_digest` (hash of context pack). + - `summary`, `conflicts`, `remediation`, `citations`. + - `generated_at`, `model_id`, `profile` (Sovereign/FIPS etc.). + - `signatures` (optional DSSE if run in deterministic mode). +- Offline bundle format contains `summary.md`, `citations.json`, `context_manifest.json`, `signatures/`. + +## 6) Profiles & sovereignty + +- **Profiles:** `default`, `fips-local` (FIPS-compliant local model), `gost-local`, `cloud-openai` (optional, disabled by default). Each profile defines allowed models, key management, and telemetry endpoints. +- **CryptoProfile/RootPack integration:** generated artefacts can be signed using configured CryptoProfile to satisfy procurement/trust requirements. + +## 7) APIs + +- `POST /v1/advisory-ai/summaries` — generate (or retrieve cached) summary for `{advisoryKey, artifactId, policyVersion}`. +- `POST /v1/advisory-ai/conflicts` — explain conflicting VEX statements with trust ranking. +- `POST /v1/advisory-ai/remediation` — fetch remediation plan with target fix versions, prerequisites, verification steps. +- `GET /v1/advisory-ai/outputs/{hash}` — retrieve cached artefact (used by CLI/Console/Export Center). + +All endpoints accept `profile` parameter (default `fips-local`) and return `output_hash`, `input_digest`, and `citations` for verification. + +## 8) Observability + +- Metrics: `advisory_ai_requests_total{profile,type}`, `advisory_ai_latency_seconds`, `advisory_ai_validation_failures_total`. +- Logs: include `output_hash`, `input_digest`, `profile`, `model_id`, `tenant`, `artifacts`. Sensitive context is not logged. +- Traces: spans for retrieval, prompt assembly, model inference, validation, cache write. + +## 9) Operational controls + +- Feature flags per tenant (`ai.summary.enabled`, `ai.remediation.enabled`). +- Rate limits (per tenant, per profile) enforced by Orchestrator to prevent runaway usage. +- Offline/air-gapped deployments run local models packaged with Offline Kit; model weights validated via manifest digests. diff --git a/docs/modules/advisory-ai/implementation_plan.md b/docs/modules/advisory-ai/implementation_plan.md new file mode 100644 index 00000000..5be64b7c --- /dev/null +++ b/docs/modules/advisory-ai/implementation_plan.md @@ -0,0 +1,19 @@ +# Implementation plan — Advisory AI + +## Current objectives +- Deliver Epic milestones summarised below while maintaining determinism and offline parity. +- Keep documentation, telemetry, and runbooks aligned with sprint outcomes. + +## Workstreams +- Roadmap: reconcile open stories in ../../TASKS.md with module backlog. +- Delivery: ship features outlined in the epic while preserving AOC guardrails. +- Validation: extend tests/fixtures to guarantee reproducibility and provenance. + +## Epic milestones +- Epic 8: Advisory AI Assistant. +- DOCS-AI stories to be tracked in ../../TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up work. +- Sync with owners listed in docs/implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/modules/attestor/AGENTS.md b/docs/modules/attestor/AGENTS.md new file mode 100644 index 00000000..02066f19 --- /dev/null +++ b/docs/modules/attestor/AGENTS.md @@ -0,0 +1,22 @@ +# Attestor agent guide + +## Mission +Attestor moves signed evidence through the trust chain by accepting DSSE bundles from Signer, registering them with Rekor v2, and serving deterministic verification payloads to other services. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. diff --git a/docs/modules/attestor/README.md b/docs/modules/attestor/README.md new file mode 100644 index 00000000..b842aefc --- /dev/null +++ b/docs/modules/attestor/README.md @@ -0,0 +1,54 @@ +# StellaOps Attestor + +Attestor converts signed DSSE evidence from the Signer into transparency-log proofs and verifiable reports for every downstream surface (Policy Engine, Export Center, CLI, Console, Scheduler). It is the trust backbone that proves SBOM, scan, VEX, and policy artefacts were signed, witnessed, and preserved without tampering. + +## Why it exists +- **Evidence first:** organisations need portable, verifiable attestations that prove build provenance, SBOM availability, policy verdicts, and VEX statements. +- **Policy enforcement:** verification policies ensure only approved issuers, key types, witnesses, and freshness windows are accepted. +- **Sovereign/offline-ready:** Attestor archives envelopes, signatures, and proofs so air-gapped deployments can replay verification without contacting external services. + +## Roles & surfaces +- **Subjects:** immutable digests for container images, SBOMs, reports, and policy bundles. +- **Issuers:** builders, scanners, policy engines, or operators signing DSSE envelopes using keyless (Fulcio), KMS/HSM, or FIDO2 keys. +- **Consumers:** CLI/SDK, Console, Export Center, Scanner, Policy Engine, and Notify retrieving verification bundles or triggering policy checks. +- **Scopes:** Authority issues `attestor.write`, `attestor.verify`, `attestor.read`, and administrative scopes for issuer/key management; every call is bound with mTLS + DPoP. + +## Supported payloads +- `StellaOps.BuildProvenance@1`, `StellaOps.SBOMAttestation@1` +- `StellaOps.ScanResults@1`, `StellaOps.VEXAttestation@1` +- `StellaOps.PolicyEvaluation@1`, `StellaOps.RiskProfileEvidence@1` +All predicates capture subjects, issuer metadata, policy context, materials, optional witnesses, and versioned schemas. Unsupported predicates return `422 predicate_unsupported`. + +## Trust & envelope model +- DSSE envelopes are canonicalised, hashed, and stored alongside the Rekor UUID, index, and proof. +- Signature modes span keyless (Fulcio), keyful (KMS/HSM), and hardware-backed (FIDO2). Multiple signatures are supported per envelope. +- Proofs include Merkle inclusion path, checkpoint metadata, optional witness endorsements, and cached verification verdicts. +- CAS/object storage retains envelopes + provenance for later replay; Rekor backends may be primary plus mirrors. + +## UI, CLI, and SDK workflows +- **Console:** Evidence browser, verification reports, chain-of-custody graph, issuer/key management, attestation workbench, and bulk verification flows. +- **CLI / SDK:** `stella attest sign|verify|list|fetch|key` commands plus language SDKs to integrate build pipelines and offline verification scripts. +- **Policy Studio:** Verification policies author required predicate types, issuers, witness requirements, and freshness windows; simulations show enforcement impact. + +## Storage, offline & air-gap posture +- MongoDB stores entry metadata, dedupe keys, and audit events; object storage optionally archives DSSE bundles. +- Export Center packages attestation bundles (`stella export attestation-bundle`) for Offline Kit delivery. +- Transparency logs can be mirrored; offline mode records gaps and provides compensating controls. + +## Observability & performance +- Metrics: `attestor_submission_total`, `attestor_verify_seconds`, `attestor_cache_hit_ratio`, `attestor_rekor_latency_seconds`. +- Logs capture tenant, issuer, subject digests, Rekor UUID, proof status, and policy verdict. +- Performance target: ≥1 000 envelopes/minute per worker with cached verification, batched operations, and concurrency controls. + +## Key integrations +- Signer (DSSE source), Authority (scopes & tenancy), Export Center (attestation bundles), Policy Engine (verification policies), Scanner/Excititor (subject evidence), Notify (key rotation & verification alerts), Observability stack (dashboards/alerts). + +## Backlog references +- DOCS-ATTEST-73-001 … DOCS-ATTEST-75-002 (Attestor console, key management, air-gap bundles) in ../../TASKS.md. +- EXPORT-ATTEST-75-002 (Export Center attestation packaging) in ../export-center/TASKS.md. + +## Epic alignment +- **Epic 19 – Attestor Console:** console experience, verification APIs, issuer/key governance, transparency integration, and offline bundles. +- **Epic 10 – Export Center:** provenance alignment so exports carry signed manifests and attestation bundles. + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/modules/attestor/TASKS.md b/docs/modules/attestor/TASKS.md new file mode 100644 index 00000000..5b13b598 --- /dev/null +++ b/docs/modules/attestor/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Attestor + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| ATTESTOR-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| ATTESTOR-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| ATTESTOR-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_ATTESTOR.md b/docs/modules/attestor/architecture.md similarity index 85% rename from docs/ARCHITECTURE_ATTESTOR.md rename to docs/modules/attestor/architecture.md index 9ea10b2c..7fddbd17 100644 --- a/docs/ARCHITECTURE_ATTESTOR.md +++ b/docs/modules/attestor/architecture.md @@ -1,5 +1,7 @@ # component_architecture_attestor.md — **Stella Ops Attestor** (2025Q4) +> Derived from Epic 19 – Attestor Console with provenance hooks aligned to the Export Center bundle workflows scoped in Epic 10. + > **Scope.** Implementation‑ready architecture for the **Attestor**: the service that **submits** DSSE envelopes to **Rekor v2**, retrieves/validates inclusion proofs, caches results, and exposes verification APIs. It accepts DSSE **only** from the **Signer** over mTLS, enforces chain‑of‑trust to Stella Ops roots, and returns `{uuid, index, proof, logURL}` to calling services (Scanner.WebService for SBOMs; backend for final reports; Excititor exports when configured). --- @@ -33,6 +35,47 @@ Trust boundary: **Only the Signer** is allowed to call submission endpoints; enf --- +### Roles, identities & scopes +- **Subjects** — immutable digests for artifacts (container images, SBOMs, reports) referenced in DSSE envelopes. +- **Issuers** — authenticated builders/scanners/policy engines signing evidence; tracked with mode (`keyless`, `kms`, `hsm`, `fido2`) and tenant scope. +- **Consumers** — Scanner, Export Center, CLI, Console, Policy Engine that verify proofs using Attestor APIs. +- **Authority scopes** — `attestor.write`, `attestor.verify`, `attestor.read`, and administrative scopes for key management; all calls mTLS/DPoP-bound. + +### Supported predicate types +- `StellaOps.BuildProvenance@1` +- `StellaOps.SBOMAttestation@1` +- `StellaOps.ScanResults@1` +- `StellaOps.PolicyEvaluation@1` +- `StellaOps.VEXAttestation@1` +- `StellaOps.RiskProfileEvidence@1` + +Each predicate embeds subject digests, issuer metadata, policy context, materials, and optional transparency hints. Unsupported predicates return `422 predicate_unsupported`. + +### Envelope & signature model +- DSSE envelopes canonicalised (stable JSON ordering) prior to hashing. +- Signature modes: keyless (Fulcio cert chain), keyful (KMS/HSM), hardware (FIDO2/WebAuthn). Multiple signatures allowed. +- Rekor entry stores bundle hash, certificate chain, and optional witness endorsements. +- Archive CAS retains original envelope plus metadata for offline verification. + +### Verification pipeline overview +1. Fetch envelope (from request, cache, or storage) and validate DSSE structure. +2. Verify signature(s) against configured trust roots; evaluate issuer policy. +3. Retrieve or acquire inclusion proof from Rekor (primary + optional mirror). +4. Validate Merkle proof against checkpoint; optionally verify witness endorsement. +5. Return cached verification bundle including policy verdict and timestamps. + +### UI & CLI touchpoints +- Console: Evidence browser, verification report, chain-of-custody graph, issuer/key management, attestation workbench, bulk verification views. +- CLI: `stella attest sign|verify|list|fetch|key` with offline verification and export bundle support. +- SDKs expose sign/verify primitives for build pipelines. + +### Performance & observability targets +- Throughput goal: ≥1 000 envelopes/minute per worker with cached verification. +- Metrics: `attestor_submission_total`, `attestor_verify_seconds`, `attestor_rekor_latency_seconds`, `attestor_cache_hit_ratio`. +- Logs include `tenant`, `issuer`, `subjectDigest`, `rekorUuid`, `proofStatus`; traces cover submission → Rekor → cache → response path. + +--- + ## 2) Data model (Mongo) Database: `attestor` diff --git a/docs/modules/attestor/implementation_plan.md b/docs/modules/attestor/implementation_plan.md new file mode 100644 index 00000000..c805be7d --- /dev/null +++ b/docs/modules/attestor/implementation_plan.md @@ -0,0 +1,74 @@ +# Implementation plan — Attestor + +## Delivery phases +- **Phase 1 – Foundations** + Build the Attestor service skeleton, DSSE bundle ingestion, mTLS/OpTok enforcement, Rekor v2 client, and cache the `{uuid,index,proof}` tuple. Publish base API (`POST /rekor/entries`, `GET /entries/{uuid}`) and Mongo schemas. +- **Phase 2 – Policies & UI** + Deliver verification policy authoring (Policy Studio integration), console views (evidence browser, verification reports, issuer management), and CLI verbs (`stella attest sign|verify|list|fetch`). +- **Phase 3 – Scan & VEX support** + Accept SBOM, ScanResults, VEX, and PolicyEvaluation predicates; integrate with Scanner, Export Center, Excititor, and Policy Engine pipelines. Ensure AOC invariants on ingestion. +- **Phase 4 – Transparency & keys** + Add multi-log submission (primary + mirror), witness endorsements, KMS/HSM/FIDO2 drivers, key rotation/revocation workflows, and audit trails. +- **Phase 5 – Bulk & air gap** + Implement batch submission/verification, DSSE archival to CAS/object storage, export/import bundles for Offline Kit, and mirror transparency log snapshots. +- **Phase 6 – Performance & hardening** + Optimise cache usage, parallel verification (target ≥1 k envelopes/minute per worker), extend observability (metrics/logs/traces), fuzz parsers, and finalise incident playbooks. + +## Work breakdown +- **Attestor service & libraries** + - DSSE validation pipeline (payload whitelist, signature verification, trust roots). + - Rekor client with inclusion-proof acquisition, retry/backoff, mirroring controls. + - Mongo repositories for entries, dedupe, audit; CAS storage for DSSE envelopes. + - Batch submission/verification APIs, verification cache, deterministic serialization. + - Observability hooks: metrics (`attestor_submission_total`, `attestor_verify_seconds`), structured logs, OpenTelemetry traces. +- **Signer & Authority integration** + - Enforce mTLS peer validation, Authority scope mapping (`attestor.write`, `attestor.verify`), and DPoP binding. + - Provide signer identity attestation metadata consumed by Attestor. +- **Policy & Console** + - Extend Policy Studio with `VerificationPolicy` authoring, approvals, and simulated results. + - Console workflows: Evidence browser, verification reports, chain-of-custody graph, key management UI, bulk verification screens. +- **CLI & SDK** + - `stella attest` command group (sign/verify/list/fetch/key management) with DSSE canonicalisation and cosign interoperability. + - SDK helpers for DSSE envelope creation, verification, and proof inspection. +- **Export Center & Offline Kit** + - Export Center adapters for attestation bundles; CLI/Console flows to export & import evidence in air-gapped environments. + - Offline Kit scripts for replaying verification, mirroring transparency logs, and reporting gaps. +- **Security & key management** + - KMS/HSM/FIDO2 driver abstraction, key rotation and revocation runbooks, witness endorsements, and revocation telemetry. +- **Docs & training** + - Update module dossier (overview, architecture, implementation plan), key management guides, transparency reference, CLI/Console documentation, and air-gap runbooks. + +## Cross-module dependencies +- **Policy Studio / Policy Engine:** verification policy artefacts, explain integration, remediation hints. +- **Export Center:** attestation bundle export/import, provenance linking. +- **Authority & Tenancy:** scopes, identity attestations, tenant-aware issuer catalogues. +- **Notifications:** attestation success/failure events, key rotation alerts. +- **Observability:** dashboards and alerting for signing/verification pipelines. + +## Acceptance criteria +- Service ingests DSSE envelopes for all supported predicate types, logs them to configured transparency logs, and returns proofs with deterministic hashes. +- Verification APIs/CLI/UI validate signatures, inclusion proofs, and policy compliance; cached verification accelerates repeated checks. +- Verification policies gate attestation usage, enforcing issuer, freshness, signature count, and witness requirements. +- Export Center and Offline Kit workflows bundle attestations and replay verification offline. +- Observability coverage includes metrics, traces, logs, audit events, and alert triggers for key compromise, log outages, and verification failure spikes. +- Performance target met (≥1 k envelopes/minute per worker) with horizontal scaling. + +## Risks & mitigations +- **Key compromise or leakage:** enforce hardware-backed keys, rotation procedures, revocation checks, and incident runbooks. +- **Parser bugs / malformed DSSE:** fuzz DSSE and predicate schemas, strict schema validation, fail closed. +- **Transparency outage:** mirror logs, support witness endorsements, queue submissions for retry with exponential backoff. +- **Policy complexity:** ship curated starter policies, provide simulation tooling, and document common scenarios. +- **Offline gaps:** archive bundles and proof material, surface gaps to operators, and document compensating controls. + +## Test strategy +- **Unit:** DSSE validation, Rekor client, dedupe logic, key drivers, policy enforcement. +- **Integration:** submit/verify flows across predicate types, multi-log publishing, batch operations, CLI/UI end-to-end exercises. +- **Security:** tenant isolation, scope enforcement, key rotation regression, tamper detection. +- **Performance:** throughput benchmarks, cache hit-rate monitoring, large batch verification. +- **Chaos:** inject Rekor outages, network failures, corrupt bundles; ensure graceful degradation and auditable alerts. + +## Definition of done +- Phased milestones delivered with telemetry, documentation, and runbooks in place. +- CLI/Console parity verified; Offline Kit procedures validated in sealed environment. +- Cross-module dependencies acknowledged in ./TASKS.md and ../../TASKS.md. +- Documentation set refreshed (overview, architecture, key management, transparency, CLI/UI) with imposed rule statement. diff --git a/docs/modules/authority/AGENTS.md b/docs/modules/authority/AGENTS.md new file mode 100644 index 00000000..a1af49e0 --- /dev/null +++ b/docs/modules/authority/AGENTS.md @@ -0,0 +1,22 @@ +# Authority agent guide + +## Mission +Authority is the platform OIDC/OAuth2 control plane that mints short-lived, sender-constrained operational tokens (OpToks) for every StellaOps service and tool. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/authority/README.md b/docs/modules/authority/README.md new file mode 100644 index 00000000..24d1c2b3 --- /dev/null +++ b/docs/modules/authority/README.md @@ -0,0 +1,40 @@ +# StellaOps Authority + +Authority is the platform OIDC/OAuth2 control plane that mints short-lived, sender-constrained operational tokens (OpToks) for every StellaOps service and tool. + +## Responsibilities +- Expose device-code, auth-code, and client-credential flows with DPoP or mTLS binding. +- Manage signing keys, JWKS rotation, and PoE integration for plan enforcement. +- Emit structured audit events and enforce tenant-aware scope policies. +- Provide plugin surface for custom identity providers and credential validators. + +## Key components +- `StellaOps.Authority` web host. +- `StellaOps.Authority.Plugin.*` extensions for secret stores, identity bridges, and OpTok validation. +- Telemetry and audit pipeline feeding Security/Observability stacks. + +## Integrations & dependencies +- Signer/Attestor for PoE and OpTok introspection. +- CLI/UI for login flows and token management. +- Scheduler/Scanner for machine-to-machine scope enforcement. + +## Operational notes +- MongoDB for tenant, client, and token state. +- Key material in KMS/HSM with rotation runbooks (see ./operations/key-rotation.md). +- Grafana/Prometheus dashboards for auth latency/issuance. + +## Related resources +- ./operations/backup-restore.md +- ./operations/key-rotation.md +- ./operations/monitoring.md +- ./operations/grafana-dashboard.json + +## Backlog references +- DOCS-SEC-62-001 (scope hardening doc) in ../../TASKS.md. +- AUTH-POLICY-20-001/002 follow-ups in src/Authority/StellaOps.Authority/TASKS.md. + +## Epic alignment +- **Epic 1 – AOC enforcement:** enforce OpTok scopes and guardrails supporting raw ingestion boundaries. +- **Epic 2 – Policy Engine & Editor:** supply policy evaluation/principal scopes and short-lived tokens for evaluator workflows. +- **Epic 4 – Policy Studio:** integrate approval/promotion signatures and policy registry access controls. +- **Epic 14 – Identity & Tenancy:** deliver tenant isolation, RBAC hierarchies, and governance tooling for authentication. diff --git a/docs/modules/authority/TASKS.md b/docs/modules/authority/TASKS.md new file mode 100644 index 00000000..ba0f6b46 --- /dev/null +++ b/docs/modules/authority/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Authority + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| AUTHORITY-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| AUTHORITY-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| AUTHORITY-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_AUTHORITY.md b/docs/modules/authority/architecture.md similarity index 96% rename from docs/ARCHITECTURE_AUTHORITY.md rename to docs/modules/authority/architecture.md index 26b5ad4f..f580d4f4 100644 --- a/docs/ARCHITECTURE_AUTHORITY.md +++ b/docs/modules/authority/architecture.md @@ -1,4 +1,6 @@ -# component_architecture_authority.md — **Stella Ops Authority** (2025Q4) +# component_architecture_authority.md — **Stella Ops Authority** (2025Q4) + +> Consolidates identity and tenancy requirements documented across the AOC, Policy, and Platform guides, along with the dedicated Authority implementation plan. > **Scope.** Implementation‑ready architecture for **Stella Ops Authority**: the on‑prem **OIDC/OAuth2** service that issues **short‑lived, sender‑constrained operational tokens (OpToks)** to first‑party services and tools. Covers protocols (DPoP & mTLS binding), token shapes, endpoints, storage, rotation, HA, RBAC, audit, and testing. This component is the trust anchor for *who* is calling inside a Stella Ops installation. (Entitlement is proven separately by **PoE** from the cloud Licensing Service; Authority does not issue PoE.) diff --git a/docs/modules/authority/implementation_plan.md b/docs/modules/authority/implementation_plan.md new file mode 100644 index 00000000..f6f83d36 --- /dev/null +++ b/docs/modules/authority/implementation_plan.md @@ -0,0 +1,22 @@ +# Implementation plan — Authority + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 1 – AOC enforcement:** deliver OpTok scopes, guardrails, and AOC verifier hooks for ingestion services. +- **Epic 2 – Policy Engine & Editor:** support policy evaluator flows (device-code, client credentials, scope sandboxing). +- **Epic 4 – Policy Studio:** provide registry/promotion signing, approvals, and fresh-auth prompts. +- **Epic 14 – Identity & Tenancy:** implement tenant isolation, RBAC hierarchies, audit trails, and PoE integration. +- Track additional work (DOCS-SEC-62-001, AUTH-POLICY-20-001/002) in ../../TASKS.md and src/Authority/**/TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ops/authority-backup-restore.md b/docs/modules/authority/operations/backup-restore.md similarity index 100% rename from docs/ops/authority-backup-restore.md rename to docs/modules/authority/operations/backup-restore.md diff --git a/docs/ops/authority-grafana-dashboard.json b/docs/modules/authority/operations/grafana-dashboard.json similarity index 100% rename from docs/ops/authority-grafana-dashboard.json rename to docs/modules/authority/operations/grafana-dashboard.json diff --git a/docs/ops/authority-key-rotation.md b/docs/modules/authority/operations/key-rotation.md similarity index 96% rename from docs/ops/authority-key-rotation.md rename to docs/modules/authority/operations/key-rotation.md index 1df76543..f1c88a13 100644 --- a/docs/ops/authority-key-rotation.md +++ b/docs/modules/authority/operations/key-rotation.md @@ -1,94 +1,94 @@ -# Authority Signing Key Rotation Playbook - -> **Status:** Authored 2025-10-12 as part of OPS3.KEY-ROTATION rollout. -> Use together with `docs/11_AUTHORITY.md` (Authority service guide) and the automation shipped under `ops/authority/`. - -## 1. Overview - -Authority publishes JWKS and revocation bundles signed with ES256 keys. To rotate those keys without downtime we now provide: - -- **Automation script:** `ops/authority/key-rotation.sh` - Shell helper that POSTS to `/internal/signing/rotate`, supports metadata, dry-run, and confirms JWKS afterwards. -- **CI workflow:** `.gitea/workflows/authority-key-rotation.yml` - Manual dispatch workflow that pulls environment-specific secrets, runs the script, and records the result. Works across staging/production by passing the `environment` input. - -This playbook documents the repeatable sequence for all environments. - -## 2. Pre-requisites - -1. **Generate a new PEM key (per environment)** - ```bash - openssl ecparam -name prime256v1 -genkey -noout \ - -out certificates/authority-signing--.pem - chmod 600 certificates/authority-signing--.pem - ``` -2. **Stash the previous key** under the same volume so it can be referenced in `signing.additionalKeys` after rotation. -3. **Ensure secrets/vars exist in Gitea** - - `_AUTHORITY_BOOTSTRAP_KEY` - - `_AUTHORITY_URL` - - Optional shared defaults `AUTHORITY_BOOTSTRAP_KEY`, `AUTHORITY_URL`. - -## 3. Executing the rotation - -### Option A – via CI workflow (recommended) - -1. Navigate to **Actions → Authority Key Rotation**. -2. Provide inputs: - - `environment`: `staging`, `production`, etc. - - `key_id`: new `kid` (e.g. `authority-signing-2025-dev`). - - `key_path`: path as seen by the Authority service (e.g. `../certificates/authority-signing-2025-dev.pem`). - - Optional `metadata`: comma-separated `key=value` pairs (for audit trails). -3. Trigger. The workflow: - - Reads the bootstrap key/URL from secrets. - - Runs `ops/authority/key-rotation.sh`. - - Prints the JWKS response for verification. - -### Option B – manual shell invocation - -```bash -AUTHORITY_BOOTSTRAP_KEY=$(cat /secure/authority-bootstrap.key) \ -./ops/authority/key-rotation.sh \ - --authority-url https://authority.example.com \ - --key-id authority-signing-2025-dev \ - --key-path ../certificates/authority-signing-2025-dev.pem \ - --meta rotatedBy=ops --meta changeTicket=OPS-1234 -``` - -Use `--dry-run` to inspect the payload before execution. - -## 4. Post-rotation checklist - -1. Update `authority.yaml` (or environment-specific overrides): - - Set `signing.activeKeyId` to the new key. - - Set `signing.keyPath` to the new PEM. - - Append the previous key into `signing.additionalKeys`. - - Ensure `keySource`/`provider` match the values passed to the script. -2. Run `stellaops-cli auth revoke export` so revocation bundles are re-signed with the new key. -3. Confirm `/jwks` lists the new `kid` with `status: "active"` and the previous one as `retired`. -4. Archive the old key securely; keep it available until all tokens/bundles signed with it have expired. - -## 5. Development key state - -For the sample configuration (`etc/authority.yaml.sample`) we minted a placeholder dev key: - -- Active: `authority-signing-2025-dev` (`certificates/authority-signing-2025-dev.pem`) -- Retired: `authority-signing-dev` - -Treat these as examples; real environments must maintain their own PEM material. - -## 6. References - -- `docs/11_AUTHORITY.md` – Architecture and rotation SOP (Section 5). -- `docs/ops/authority-backup-restore.md` – Recovery flow referencing this playbook. -- `ops/authority/README.md` – CLI usage and examples. -- `scripts/rotate-policy-cli-secret.sh` – Helper to mint new `policy-cli` shared secrets when policy scope bundles change. - -## 7. Appendix — Policy CLI secret rotation - -Scope migrations such as AUTH-POLICY-23-004 require issuing fresh credentials for the `policy-cli` client. Use the helper script committed with the repo to keep secrets deterministic across environments. - -```bash -./scripts/rotate-policy-cli-secret.sh --output etc/secrets/policy-cli.secret -``` - -The script writes a timestamped header and a random secret into the target file. Use `--dry-run` when generating material for external secret stores. After updating secrets in staging/production, recycle the Authority pods and confirm the new client credentials work before the next release freeze. +# Authority Signing Key Rotation Playbook + +> **Status:** Authored 2025-10-12 as part of OPS3.KEY-ROTATION rollout. +> Use together with `docs/11_AUTHORITY.md` (Authority service guide) and the automation shipped under `ops/authority/`. + +## 1. Overview + +Authority publishes JWKS and revocation bundles signed with ES256 keys. To rotate those keys without downtime we now provide: + +- **Automation script:** `ops/authority/key-rotation.sh` + Shell helper that POSTS to `/internal/signing/rotate`, supports metadata, dry-run, and confirms JWKS afterwards. +- **CI workflow:** `.gitea/workflows/authority-key-rotation.yml` + Manual dispatch workflow that pulls environment-specific secrets, runs the script, and records the result. Works across staging/production by passing the `environment` input. + +This playbook documents the repeatable sequence for all environments. + +## 2. Pre-requisites + +1. **Generate a new PEM key (per environment)** + ```bash + openssl ecparam -name prime256v1 -genkey -noout \ + -out certificates/authority-signing--.pem + chmod 600 certificates/authority-signing--.pem + ``` +2. **Stash the previous key** under the same volume so it can be referenced in `signing.additionalKeys` after rotation. +3. **Ensure secrets/vars exist in Gitea** + - `_AUTHORITY_BOOTSTRAP_KEY` + - `_AUTHORITY_URL` + - Optional shared defaults `AUTHORITY_BOOTSTRAP_KEY`, `AUTHORITY_URL`. + +## 3. Executing the rotation + +### Option A – via CI workflow (recommended) + +1. Navigate to **Actions → Authority Key Rotation**. +2. Provide inputs: + - `environment`: `staging`, `production`, etc. + - `key_id`: new `kid` (e.g. `authority-signing-2025-dev`). + - `key_path`: path as seen by the Authority service (e.g. `../certificates/authority-signing-2025-dev.pem`). + - Optional `metadata`: comma-separated `key=value` pairs (for audit trails). +3. Trigger. The workflow: + - Reads the bootstrap key/URL from secrets. + - Runs `ops/authority/key-rotation.sh`. + - Prints the JWKS response for verification. + +### Option B – manual shell invocation + +```bash +AUTHORITY_BOOTSTRAP_KEY=$(cat /secure/authority-bootstrap.key) \ +./ops/authority/key-rotation.sh \ + --authority-url https://authority.example.com \ + --key-id authority-signing-2025-dev \ + --key-path ../certificates/authority-signing-2025-dev.pem \ + --meta rotatedBy=ops --meta changeTicket=OPS-1234 +``` + +Use `--dry-run` to inspect the payload before execution. + +## 4. Post-rotation checklist + +1. Update `authority.yaml` (or environment-specific overrides): + - Set `signing.activeKeyId` to the new key. + - Set `signing.keyPath` to the new PEM. + - Append the previous key into `signing.additionalKeys`. + - Ensure `keySource`/`provider` match the values passed to the script. +2. Run `stellaops-cli auth revoke export` so revocation bundles are re-signed with the new key. +3. Confirm `/jwks` lists the new `kid` with `status: "active"` and the previous one as `retired`. +4. Archive the old key securely; keep it available until all tokens/bundles signed with it have expired. + +## 5. Development key state + +For the sample configuration (`etc/authority.yaml.sample`) we minted a placeholder dev key: + +- Active: `authority-signing-2025-dev` (`certificates/authority-signing-2025-dev.pem`) +- Retired: `authority-signing-dev` + +Treat these as examples; real environments must maintain their own PEM material. + +## 6. References + +- `docs/11_AUTHORITY.md` – Architecture and rotation SOP (Section 5). +- `docs/modules/authority/operations/backup-restore.md` – Recovery flow referencing this playbook. +- `ops/authority/README.md` – CLI usage and examples. +- `scripts/rotate-policy-cli-secret.sh` – Helper to mint new `policy-cli` shared secrets when policy scope bundles change. + +## 7. Appendix — Policy CLI secret rotation + +Scope migrations such as AUTH-POLICY-23-004 require issuing fresh credentials for the `policy-cli` client. Use the helper script committed with the repo to keep secrets deterministic across environments. + +```bash +./scripts/rotate-policy-cli-secret.sh --output etc/secrets/policy-cli.secret +``` + +The script writes a timestamped header and a random secret into the target file. Use `--dry-run` when generating material for external secret stores. After updating secrets in staging/production, recycle the Authority pods and confirm the new client credentials work before the next release freeze. diff --git a/docs/ops/authority-monitoring.md b/docs/modules/authority/operations/monitoring.md similarity index 97% rename from docs/ops/authority-monitoring.md rename to docs/modules/authority/operations/monitoring.md index 60717602..2f5e8e5f 100644 --- a/docs/ops/authority-monitoring.md +++ b/docs/modules/authority/operations/monitoring.md @@ -1,83 +1,83 @@ -# Authority Monitoring & Alerting Playbook - -## Telemetry Sources -- **Traces:** Activity source `StellaOps.Authority` emits spans for every token flow (`authority.token.validate_*`, `authority.token.handle_*`, `authority.token.validate_access`). Key tags include `authority.endpoint`, `authority.grant_type`, `authority.username`, `authority.client_id`, and `authority.identity_provider`. -- **Metrics:** OpenTelemetry instrumentation (`AddAspNetCoreInstrumentation`, `AddHttpClientInstrumentation`, custom meter `StellaOps.Authority`) exports: - - `http.server.request.duration` histogram (`http_route`, `http_status_code`, `authority.endpoint` tag via `aspnetcore` enrichment). - - `process.runtime.gc.*`, `process.runtime.dotnet.*` (from `AddRuntimeInstrumentation`). -- **Logs:** Serilog writes structured events to stdout. Notable templates: - - `"Password grant verification failed ..."` and `"Plugin {PluginName} denied access ... due to lockout"` (lockout spike detector). - - `"Password grant validation failed for {Username}: provider '{Provider}' does not support MFA required for exception approvals."` (identifies users attempting `exceptions:approve` without MFA support; tie to fresh-auth errors). - - `"Client credentials validation failed for {ClientId}: exception scopes require tenant assignment."` (signals misconfigured exception service identities). - - `"Granting StellaOps bypass for remote {RemoteIp}"` (bypass usage). - - `"Rate limit exceeded for path {Path} from {RemoteIp}"` (limiter alerts). - -## Prometheus Metrics to Collect -| Metric | Query | Purpose | -| --- | --- | --- | -| `token_requests_total` | `sum by (grant_type, status) (rate(http_server_duration_seconds_count{service_name="stellaops-authority", http_route="/token"}[5m]))` | Token issuance volume per grant type (`grant_type` comes via `authority.grant_type` span attribute → Exemplars in Grafana). | -| `token_failure_ratio` | `sum(rate(http_server_duration_seconds_count{service_name="stellaops-authority", http_route="/token", http_status_code=~"4..|5.."}[5m])) / sum(rate(http_server_duration_seconds_count{service_name="stellaops-authority", http_route="/token"}[5m]))` | Alert when > 5 % for 10 min. | -| `authorize_rate_limit_hits` | `sum(rate(aspnetcore_rate_limiting_rejections_total{service_name="stellaops-authority", limiter="authority-token"}[5m]))` | Detect rate limiting saturations (requires OTEL ASP.NET rate limiter exporter). | -| `lockout_events` | `sum by (plugin) (rate(log_messages_total{app="stellaops-authority", level="Warning", message_template="Plugin {PluginName} denied access for {Username} due to lockout (retry after {RetryAfter})."}[5m]))` | Derived from Loki/Promtail log counter. | -| `bypass_usage_total` | `sum(rate(log_messages_total{app="stellaops-authority", level="Information", message_template="Granting StellaOps bypass for remote {RemoteIp}; required scopes {RequiredScopes}."}[5m]))` | Track trusted bypass invocations. | - -> **Exporter note:** Enable `aspnetcore` meters (`dotnet-counters` name `Microsoft.AspNetCore.Hosting`), or configure the OpenTelemetry Collector `metrics` pipeline with `metric_statements` to remap histogram counts into the shown series. - -## Alert Rules -1. **Token Failure Surge** - - _Expression_: `token_failure_ratio > 0.05` - - _For_: `10m` - - _Labels_: `severity="critical"` - - _Annotations_: Include `topk(5, sum by (authority_identity_provider) (increase(authority_token_rejections_total[10m])))` as diagnostic hint (requires span → metric transformation). -2. **Lockout Spike** - - _Expression_: `sum(rate(log_messages_total{message_template="Plugin {PluginName} denied access for {Username} due to lockout (retry after {RetryAfter})."}[15m])) > 10` - - _For_: `15m` - - Investigate credential stuffing; consider temporarily tightening `RateLimiting.Token`. -3. **Bypass Threshold** - - _Expression_: `sum(rate(log_messages_total{message_template="Granting StellaOps bypass for remote {RemoteIp}; required scopes {RequiredScopes}."}[5m])) > 1` - - _For_: `5m` - - Alert severity `warning` — verify the calling host list. -4. **Rate Limiter Saturation** - - _Expression_: `sum(rate(aspnetcore_rate_limiting_rejections_total{service_name="stellaops-authority"}[5m])) > 0` - - Escalate if sustained for 5 min; confirm trusted clients aren’t misconfigured. - -## Grafana Dashboard -- Import `docs/ops/authority-grafana-dashboard.json` to provision baseline panels: - - **Token Success vs Failure** – stacked rate visualization split by grant type. - - **Rate Limiter Hits** – bar chart showing `authority-token` and `authority-authorize`. - - **Bypass & Lockout Events** – dual-stat panel using Loki-derived counters. - - **Trace Explorer Link** – panel links to `StellaOps.Authority` span search pre-filtered by `authority.grant_type`. - -## Collector Configuration Snippets -```yaml -receivers: - otlp: - protocols: - http: -exporters: - prometheus: - endpoint: "0.0.0.0:9464" -processors: - batch: - attributes/token_grant: - actions: - - key: grant_type - action: upsert - from_attribute: authority.grant_type -service: - pipelines: - metrics: - receivers: [otlp] - processors: [attributes/token_grant, batch] - exporters: [prometheus] - logs: - receivers: [otlp] - processors: [batch] - exporters: [loki] -``` - -## Operational Checklist -- [ ] Confirm `STELLAOPS_AUTHORITY__OBSERVABILITY__EXPORTERS` enables OTLP in production builds. -- [ ] Ensure Promtail captures container stdout with Serilog structured formatting. -- [ ] Periodically validate alert noise by running load tests that trigger the rate limiter. -- [ ] Include dashboard JSON in Offline Kit for air-gapped clusters; update version header when metrics change. +# Authority Monitoring & Alerting Playbook + +## Telemetry Sources +- **Traces:** Activity source `StellaOps.Authority` emits spans for every token flow (`authority.token.validate_*`, `authority.token.handle_*`, `authority.token.validate_access`). Key tags include `authority.endpoint`, `authority.grant_type`, `authority.username`, `authority.client_id`, and `authority.identity_provider`. +- **Metrics:** OpenTelemetry instrumentation (`AddAspNetCoreInstrumentation`, `AddHttpClientInstrumentation`, custom meter `StellaOps.Authority`) exports: + - `http.server.request.duration` histogram (`http_route`, `http_status_code`, `authority.endpoint` tag via `aspnetcore` enrichment). + - `process.runtime.gc.*`, `process.runtime.dotnet.*` (from `AddRuntimeInstrumentation`). +- **Logs:** Serilog writes structured events to stdout. Notable templates: + - `"Password grant verification failed ..."` and `"Plugin {PluginName} denied access ... due to lockout"` (lockout spike detector). + - `"Password grant validation failed for {Username}: provider '{Provider}' does not support MFA required for exception approvals."` (identifies users attempting `exceptions:approve` without MFA support; tie to fresh-auth errors). + - `"Client credentials validation failed for {ClientId}: exception scopes require tenant assignment."` (signals misconfigured exception service identities). + - `"Granting StellaOps bypass for remote {RemoteIp}"` (bypass usage). + - `"Rate limit exceeded for path {Path} from {RemoteIp}"` (limiter alerts). + +## Prometheus Metrics to Collect +| Metric | Query | Purpose | +| --- | --- | --- | +| `token_requests_total` | `sum by (grant_type, status) (rate(http_server_duration_seconds_count{service_name="stellaops-authority", http_route="/token"}[5m]))` | Token issuance volume per grant type (`grant_type` comes via `authority.grant_type` span attribute → Exemplars in Grafana). | +| `token_failure_ratio` | `sum(rate(http_server_duration_seconds_count{service_name="stellaops-authority", http_route="/token", http_status_code=~"4..|5.."}[5m])) / sum(rate(http_server_duration_seconds_count{service_name="stellaops-authority", http_route="/token"}[5m]))` | Alert when > 5 % for 10 min. | +| `authorize_rate_limit_hits` | `sum(rate(aspnetcore_rate_limiting_rejections_total{service_name="stellaops-authority", limiter="authority-token"}[5m]))` | Detect rate limiting saturations (requires OTEL ASP.NET rate limiter exporter). | +| `lockout_events` | `sum by (plugin) (rate(log_messages_total{app="stellaops-authority", level="Warning", message_template="Plugin {PluginName} denied access for {Username} due to lockout (retry after {RetryAfter})."}[5m]))` | Derived from Loki/Promtail log counter. | +| `bypass_usage_total` | `sum(rate(log_messages_total{app="stellaops-authority", level="Information", message_template="Granting StellaOps bypass for remote {RemoteIp}; required scopes {RequiredScopes}."}[5m]))` | Track trusted bypass invocations. | + +> **Exporter note:** Enable `aspnetcore` meters (`dotnet-counters` name `Microsoft.AspNetCore.Hosting`), or configure the OpenTelemetry Collector `metrics` pipeline with `metric_statements` to remap histogram counts into the shown series. + +## Alert Rules +1. **Token Failure Surge** + - _Expression_: `token_failure_ratio > 0.05` + - _For_: `10m` + - _Labels_: `severity="critical"` + - _Annotations_: Include `topk(5, sum by (authority_identity_provider) (increase(authority_token_rejections_total[10m])))` as diagnostic hint (requires span → metric transformation). +2. **Lockout Spike** + - _Expression_: `sum(rate(log_messages_total{message_template="Plugin {PluginName} denied access for {Username} due to lockout (retry after {RetryAfter})."}[15m])) > 10` + - _For_: `15m` + - Investigate credential stuffing; consider temporarily tightening `RateLimiting.Token`. +3. **Bypass Threshold** + - _Expression_: `sum(rate(log_messages_total{message_template="Granting StellaOps bypass for remote {RemoteIp}; required scopes {RequiredScopes}."}[5m])) > 1` + - _For_: `5m` + - Alert severity `warning` — verify the calling host list. +4. **Rate Limiter Saturation** + - _Expression_: `sum(rate(aspnetcore_rate_limiting_rejections_total{service_name="stellaops-authority"}[5m])) > 0` + - Escalate if sustained for 5 min; confirm trusted clients aren’t misconfigured. + +## Grafana Dashboard +- Import `docs/modules/authority/operations/grafana-dashboard.json` to provision baseline panels: + - **Token Success vs Failure** – stacked rate visualization split by grant type. + - **Rate Limiter Hits** – bar chart showing `authority-token` and `authority-authorize`. + - **Bypass & Lockout Events** – dual-stat panel using Loki-derived counters. + - **Trace Explorer Link** – panel links to `StellaOps.Authority` span search pre-filtered by `authority.grant_type`. + +## Collector Configuration Snippets +```yaml +receivers: + otlp: + protocols: + http: +exporters: + prometheus: + endpoint: "0.0.0.0:9464" +processors: + batch: + attributes/token_grant: + actions: + - key: grant_type + action: upsert + from_attribute: authority.grant_type +service: + pipelines: + metrics: + receivers: [otlp] + processors: [attributes/token_grant, batch] + exporters: [prometheus] + logs: + receivers: [otlp] + processors: [batch] + exporters: [loki] +``` + +## Operational Checklist +- [ ] Confirm `STELLAOPS_AUTHORITY__OBSERVABILITY__EXPORTERS` enables OTLP in production builds. +- [ ] Ensure Promtail captures container stdout with Serilog structured formatting. +- [ ] Periodically validate alert noise by running load tests that trigger the rate limiter. +- [ ] Include dashboard JSON in Offline Kit for air-gapped clusters; update version header when metrics change. diff --git a/docs/modules/ci/AGENTS.md b/docs/modules/ci/AGENTS.md new file mode 100644 index 00000000..af0dc9c7 --- /dev/null +++ b/docs/modules/ci/AGENTS.md @@ -0,0 +1,22 @@ +# CI Recipes agent guide + +## Mission +CI module collects reproducible pipeline recipes for builds, tests, and release promotion across supported platforms. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/ci/README.md b/docs/modules/ci/README.md new file mode 100644 index 00000000..c6465332 --- /dev/null +++ b/docs/modules/ci/README.md @@ -0,0 +1,29 @@ +# StellaOps CI Recipes + +CI module collects reproducible pipeline recipes for builds, tests, and release promotion across supported platforms. + +## Responsibilities +- Provide ready-to-use pipeline snippets for ingestion, scanning, policy evaluation, and exports. +- Document required secrets/scopes and deterministic build knobs. +- Highlight offline-compatible workflows and cache strategies. + +## Key components +- Recipe catalogue in ./recipes.md. + +## Integrations & dependencies +- DevOps release workflows. +- Module-specific test suites referenced in recipes. + +## Operational notes +- Encourage reuse through templated YAML/JSON fragments. + +## Related resources +- ./recipes.md + +## Backlog references +- CI recipes refresh tracked in ../../TASKS.md under DOCS-CI stories. + +## Epic alignment +- **Epic 1 – AOC enforcement:** bake ingestion/verifier guardrails into CI recipes. +- **Epic 10 – Export Center:** provide pipeline snippets for export packaging, signing, and Offline Kit publication. +- **Epic 11 – Notifications Studio:** offer CI hooks for notification previews/tests where relevant. diff --git a/docs/modules/ci/TASKS.md b/docs/modules/ci/TASKS.md new file mode 100644 index 00000000..3438e11c --- /dev/null +++ b/docs/modules/ci/TASKS.md @@ -0,0 +1,9 @@ +# Task board — CI Recipes + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| CI RECIPES-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| CI RECIPES-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| CI RECIPES-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/modules/ci/architecture.md b/docs/modules/ci/architecture.md new file mode 100644 index 00000000..418dcdfa --- /dev/null +++ b/docs/modules/ci/architecture.md @@ -0,0 +1,7 @@ +# CI Recipes architecture + +> Reference the AOC guardrails, export workflows, and notification patterns documented in the Authority, Export Center, and Notify module guides when designing CI templates. + +This placeholder summarises the planned architecture for CI Recipes. Consolidate design details from implementation plans and upcoming epics before coding. + +Refer to the module README and implementation plan for immediate context, and update this document once component boundaries and data flows are finalised. diff --git a/docs/modules/ci/implementation_plan.md b/docs/modules/ci/implementation_plan.md new file mode 100644 index 00000000..2a03174a --- /dev/null +++ b/docs/modules/ci/implementation_plan.md @@ -0,0 +1,21 @@ +# Implementation plan — CI Recipes + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 1 – AOC enforcement:** ensure pipelines enforce schemas, provenance, and verifier jobs. +- **Epic 10 – Export Center:** add export/signing/Offline Kit automation templates. +- **Epic 11 – Notifications Studio:** document CI hooks for notification previews/tests. +- Track DOCS-CI stories in ../../TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ci/20_CI_RECIPES.md b/docs/modules/ci/recipes.md similarity index 97% rename from docs/ci/20_CI_RECIPES.md rename to docs/modules/ci/recipes.md index eadc31f3..2b21a5f8 100755 --- a/docs/ci/20_CI_RECIPES.md +++ b/docs/modules/ci/recipes.md @@ -1,248 +1,248 @@ -# Stella Ops CI Recipes — (2025‑08‑04) - -## 0 · Key variables (export these once) - -| Variable | Meaning | Typical value | -| ------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| `STELLA_URL` | Host that: ① stores the **CLI** & **SBOM‑builder** images under `/registry` **and** ② receives API calls at `https://$STELLA_URL` | `stella-ops.ci.acme.example` | -| `DOCKER_HOST` | How containers reach your Docker daemon (because we no longer mount `/var/run/docker.sock`) | `tcp://docker:2375` | -| `WORKSPACE` | Directory where the pipeline stores artefacts (SBOM file) | `$(pwd)` | -| `IMAGE` | The image you are building & scanning | `acme/backend:sha-${COMMIT_SHA}` | +# Stella Ops CI Recipes — (2025‑08‑04) + +## 0 · Key variables (export these once) + +| Variable | Meaning | Typical value | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| `STELLA_URL` | Host that: ① stores the **CLI** & **SBOM‑builder** images under `/registry` **and** ② receives API calls at `https://$STELLA_URL` | `stella-ops.ci.acme.example` | +| `DOCKER_HOST` | How containers reach your Docker daemon (because we no longer mount `/var/run/docker.sock`) | `tcp://docker:2375` | +| `WORKSPACE` | Directory where the pipeline stores artefacts (SBOM file) | `$(pwd)` | +| `IMAGE` | The image you are building & scanning | `acme/backend:sha-${COMMIT_SHA}` | | `SBOM_FILE` | Immutable SBOM name – `‑YYYYMMDDThhmmssZ.sbom.json` | `acme_backend_sha‑abc123‑20250804T153050Z.sbom.json` | > **Authority graph scopes note (2025-10-27):** CI stages that spin up the Authority compose profile now rely on the checked-in `etc/authority.yaml`. Before running integration smoke jobs, inject real secrets for every `etc/secrets/*.secret` file (Cartographer, Graph API, Policy Engine, Concelier, Excititor). The repository defaults contain `*-change-me` placeholders and Authority will reject tokens if those secrets are not overridden. Reissue CI tokens that previously used `policy:write`/`policy:submit`/`policy:edit` scopes—new bundles must request `policy:read`, `policy:author`, `policy:review`, `policy:simulate`, and (`policy:approve`/`policy:operate`/`policy:activate` when pipelines promote policies). - -```bash -export STELLA_URL="stella-ops.ci.acme.example" -export DOCKER_HOST="tcp://docker:2375" # Jenkins/Circle often expose it like this -export WORKSPACE="$(pwd)" -export IMAGE="acme/backend:sha-${COMMIT_SHA}" -export SBOM_FILE="$(echo "${IMAGE}" | tr '/:+' '__')-$(date -u +%Y%m%dT%H%M%SZ).sbom.json" -``` - ---- - -## 1 · SBOM creation strategies - -### Option A – **Buildx attested SBOM** (preferred if you can use BuildKit) - -You pass **two build args** so the Dockerfile can run the builder and copy the result out of the build context. - -```bash -docker buildx build \ - --build-arg STELLA_SBOM_BUILDER="$STELLA_URL/registry/stella-sbom-builder:latest" \ - --provenance=true --sbom=true \ - --build-arg SBOM_FILE="$SBOM_FILE" \ - -t "$IMAGE" . -``` - -**If you **cannot** use Buildx, use Option B below.** The older “run a builder stage inside the Dockerfile” pattern is unreliable for producing an SBOM of the final image. - -```Dockerfile - -ARG STELLA_SBOM_BUILDER -ARG SBOM_FILE - -FROM $STELLA_SBOM_BUILDER as sbom -ARG IMAGE -ARG SBOM_FILE -RUN $STELLA_SBOM_BUILDER build --image $IMAGE --output /out/$SBOM_FILE - -# ---- actual build stages … ---- -FROM alpine:3.20 -COPY --from=sbom /out/$SBOM_FILE / # (optional) keep or discard - -# (rest of your Dockerfile) -``` - -### Option B – **External builder step** (works everywhere; recommended baseline if Buildx isn’t available) - -*(keep this block if your pipeline already has an image‑build step that you can’t modify)* - -```bash -docker run --rm \ - -e DOCKER_HOST="$DOCKER_HOST" \ # let builder reach the daemon remotely - -v "$WORKSPACE:/workspace" \ # place SBOM beside the source code - "$STELLA_URL/registry/stella-sbom-builder:latest" \ - build --image "$IMAGE" --output "/workspace/${SBOM_FILE}" -``` - ---- - -## 2 · Scan the image & upload results - -```bash -docker run --rm \ - -e DOCKER_HOST="$DOCKER_HOST" \ # remote‑daemon pointer - -v "$WORKSPACE/${SBOM_FILE}:/${SBOM_FILE}:ro" \ # mount SBOM under same name at container root - -e STELLA_OPS_URL="https://${STELLA_URL}" \ # where the CLI posts findings - "$STELLA_URL/registry/stella-cli:latest" \ - scan --sbom "/${SBOM_FILE}" "$IMAGE" -``` - -The CLI returns **exit 0** if policies pass, **>0** if blocked — perfect for failing the job. - ---- - -## 3 · CI templates - -Below are minimal, cut‑and‑paste snippets. -**Feel free to delete Option B** if you adopt Option A. - -### 3.1 Jenkins (Declarative Pipeline) - -```groovy -pipeline { - agent { docker { image 'docker:25' args '--privileged' } } // gives us /usr/bin/docker - environment { - STELLA_URL = 'stella-ops.ci.acme.example' - DOCKER_HOST = 'tcp://docker:2375' - IMAGE = "acme/backend:${env.BUILD_NUMBER}" - SBOM_FILE = "acme_backend_${env.BUILD_NUMBER}-${new Date().format('yyyyMMdd\'T\'HHmmss\'Z\'', TimeZone.getTimeZone('UTC'))}.sbom.json" - } - stages { - stage('Build image + SBOM (Option A)') { - steps { - sh ''' - docker build \ - --build-arg STELLA_SBOM_BUILDER="$STELLA_URL/registry/stella-sbom-builder:latest" \ - --build-arg SBOM_FILE="$SBOM_FILE" \ - -t "$IMAGE" . - ''' - } - } - /* ---------- Option B fallback (when you must keep the existing build step as‑is) ---------- - stage('SBOM builder (Option B)') { - steps { - sh ''' - docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ - -v "$WORKSPACE:/workspace" \ - "$STELLA_URL/registry/stella-sbom-builder:latest" \ - build --image "$IMAGE" --output "/workspace/${SBOM_FILE}" - ''' - } - } - ------------------------------------------------------------------------------------------ */ - stage('Scan & upload') { - steps { - sh ''' - docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ - -v "$WORKSPACE/${SBOM_FILE}:/${SBOM_FILE}:ro" \ - -e STELLA_OPS_URL="https://$STELLA_URL" \ - "$STELLA_URL/registry/stella-cli:latest" \ - scan --sbom "/${SBOM_FILE}" "$IMAGE" - ''' - } - } - } -} -``` - ---- - -### 3.2 CircleCI `.circleci/config.yml` - -```yaml -version: 2.1 -jobs: - stella_scan: - docker: - - image: cimg/base:stable # baremetal image with Docker CLI - environment: - STELLA_URL: stella-ops.ci.acme.example - DOCKER_HOST: tcp://docker:2375 # Circle’s “remote Docker” socket - steps: - - checkout - - - run: - name: Compute vars - command: | - echo 'export IMAGE="acme/backend:${CIRCLE_SHA1}"' >> $BASH_ENV - echo 'export SBOM_FILE="$(echo acme/backend:${CIRCLE_SHA1} | tr "/:+" "__")-$(date -u +%Y%m%dT%H%M%SZ).sbom.json"' >> $BASH_ENV - - run: - name: Build image + SBOM (Option A) - command: | - docker build \ - --build-arg STELLA_SBOM_BUILDER="$STELLA_URL/registry/stella-sbom-builder:latest" \ - --build-arg SBOM_FILE="$SBOM_FILE" \ - -t "$IMAGE" . - # --- Option B fallback (when you must keep the existing build step as‑is) --- - #- run: - # name: SBOM builder (Option B) - # command: | - # docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ - # -v "$PWD:/workspace" \ - # "$STELLA_URL/registry/stella-sbom-builder:latest" \ - # build --image "$IMAGE" --output "/workspace/${SBOM_FILE}" - - run: - name: Scan - command: | - docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ - -v "$PWD/${SBOM_FILE}:/${SBOM_FILE}:ro" \ - -e STELLA_OPS_URL="https://$STELLA_URL" \ - "$STELLA_URL/registry/stella-cli:latest" \ - scan --sbom "/${SBOM_FILE}" "$IMAGE" -workflows: - stella: - jobs: [stella_scan] -``` - ---- - -### 3.3 Gitea Actions `.gitea/workflows/stella.yml` - -*(Gitea 1.22+ ships native Actions compatible with GitHub syntax)* - -```yaml -name: Stella Scan -on: [push] - -jobs: - stella: - runs-on: ubuntu-latest - env: - STELLA_URL: ${{ secrets.STELLA_URL }} - DOCKER_HOST: tcp://docker:2375 # provided by the docker:dind service - services: - docker: - image: docker:dind - options: >- - --privileged - steps: - - uses: actions/checkout@v4 - - - name: Compute vars - id: vars - run: | - echo "IMAGE=ghcr.io/${{ gitea.repository }}:${{ gitea.sha }}" >> $GITEA_OUTPUT - echo "SBOM_FILE=$(echo ghcr.io/${{ gitea.repository }}:${{ gitea.sha }} | tr '/:+' '__')-$(date -u +%Y%m%dT%H%M%SZ).sbom.json" >> $GITEA_OUTPUT - - - name: Build image + SBOM (Option A) - run: | - docker build \ - --build-arg STELLA_SBOM_BUILDER="${STELLA_URL}/registry/stella-sbom-builder:latest" \ - --build-arg SBOM_FILE="${{ steps.vars.outputs.SBOM_FILE }}" \ - -t "${{ steps.vars.outputs.IMAGE }}" . - - # --- Option B fallback (when you must keep the existing build step as‑is) --- - #- name: SBOM builder (Option B) - # run: | - # docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ - # -v "$(pwd):/workspace" \ - # "${STELLA_URL}/registry/stella-sbom-builder:latest" \ - # build --image "${{ steps.vars.outputs.IMAGE }}" --output "/workspace/${{ steps.vars.outputs.SBOM_FILE }}" - - - name: Scan - run: | - docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ - -v "$(pwd)/${{ steps.vars.outputs.SBOM_FILE }}:/${{ steps.vars.outputs.SBOM_FILE }}:ro" \ - -e STELLA_OPS_URL="https://${STELLA_URL}" \ - "${STELLA_URL}/registry/stella-cli:latest" \ - scan --sbom "/${{ steps.vars.outputs.SBOM_FILE }}" "${{ steps.vars.outputs.IMAGE }}" -``` - ---- - + +```bash +export STELLA_URL="stella-ops.ci.acme.example" +export DOCKER_HOST="tcp://docker:2375" # Jenkins/Circle often expose it like this +export WORKSPACE="$(pwd)" +export IMAGE="acme/backend:sha-${COMMIT_SHA}" +export SBOM_FILE="$(echo "${IMAGE}" | tr '/:+' '__')-$(date -u +%Y%m%dT%H%M%SZ).sbom.json" +``` + +--- + +## 1 · SBOM creation strategies + +### Option A – **Buildx attested SBOM** (preferred if you can use BuildKit) + +You pass **two build args** so the Dockerfile can run the builder and copy the result out of the build context. + +```bash +docker buildx build \ + --build-arg STELLA_SBOM_BUILDER="$STELLA_URL/registry/stella-sbom-builder:latest" \ + --provenance=true --sbom=true \ + --build-arg SBOM_FILE="$SBOM_FILE" \ + -t "$IMAGE" . +``` + +**If you **cannot** use Buildx, use Option B below.** The older “run a builder stage inside the Dockerfile” pattern is unreliable for producing an SBOM of the final image. + +```Dockerfile + +ARG STELLA_SBOM_BUILDER +ARG SBOM_FILE + +FROM $STELLA_SBOM_BUILDER as sbom +ARG IMAGE +ARG SBOM_FILE +RUN $STELLA_SBOM_BUILDER build --image $IMAGE --output /out/$SBOM_FILE + +# ---- actual build stages … ---- +FROM alpine:3.20 +COPY --from=sbom /out/$SBOM_FILE / # (optional) keep or discard + +# (rest of your Dockerfile) +``` + +### Option B – **External builder step** (works everywhere; recommended baseline if Buildx isn’t available) + +*(keep this block if your pipeline already has an image‑build step that you can’t modify)* + +```bash +docker run --rm \ + -e DOCKER_HOST="$DOCKER_HOST" \ # let builder reach the daemon remotely + -v "$WORKSPACE:/workspace" \ # place SBOM beside the source code + "$STELLA_URL/registry/stella-sbom-builder:latest" \ + build --image "$IMAGE" --output "/workspace/${SBOM_FILE}" +``` + +--- + +## 2 · Scan the image & upload results + +```bash +docker run --rm \ + -e DOCKER_HOST="$DOCKER_HOST" \ # remote‑daemon pointer + -v "$WORKSPACE/${SBOM_FILE}:/${SBOM_FILE}:ro" \ # mount SBOM under same name at container root + -e STELLA_OPS_URL="https://${STELLA_URL}" \ # where the CLI posts findings + "$STELLA_URL/registry/stella-cli:latest" \ + scan --sbom "/${SBOM_FILE}" "$IMAGE" +``` + +The CLI returns **exit 0** if policies pass, **>0** if blocked — perfect for failing the job. + +--- + +## 3 · CI templates + +Below are minimal, cut‑and‑paste snippets. +**Feel free to delete Option B** if you adopt Option A. + +### 3.1 Jenkins (Declarative Pipeline) + +```groovy +pipeline { + agent { docker { image 'docker:25' args '--privileged' } } // gives us /usr/bin/docker + environment { + STELLA_URL = 'stella-ops.ci.acme.example' + DOCKER_HOST = 'tcp://docker:2375' + IMAGE = "acme/backend:${env.BUILD_NUMBER}" + SBOM_FILE = "acme_backend_${env.BUILD_NUMBER}-${new Date().format('yyyyMMdd\'T\'HHmmss\'Z\'', TimeZone.getTimeZone('UTC'))}.sbom.json" + } + stages { + stage('Build image + SBOM (Option A)') { + steps { + sh ''' + docker build \ + --build-arg STELLA_SBOM_BUILDER="$STELLA_URL/registry/stella-sbom-builder:latest" \ + --build-arg SBOM_FILE="$SBOM_FILE" \ + -t "$IMAGE" . + ''' + } + } + /* ---------- Option B fallback (when you must keep the existing build step as‑is) ---------- + stage('SBOM builder (Option B)') { + steps { + sh ''' + docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ + -v "$WORKSPACE:/workspace" \ + "$STELLA_URL/registry/stella-sbom-builder:latest" \ + build --image "$IMAGE" --output "/workspace/${SBOM_FILE}" + ''' + } + } + ------------------------------------------------------------------------------------------ */ + stage('Scan & upload') { + steps { + sh ''' + docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ + -v "$WORKSPACE/${SBOM_FILE}:/${SBOM_FILE}:ro" \ + -e STELLA_OPS_URL="https://$STELLA_URL" \ + "$STELLA_URL/registry/stella-cli:latest" \ + scan --sbom "/${SBOM_FILE}" "$IMAGE" + ''' + } + } + } +} +``` + +--- + +### 3.2 CircleCI `.circleci/config.yml` + +```yaml +version: 2.1 +jobs: + stella_scan: + docker: + - image: cimg/base:stable # baremetal image with Docker CLI + environment: + STELLA_URL: stella-ops.ci.acme.example + DOCKER_HOST: tcp://docker:2375 # Circle’s “remote Docker” socket + steps: + - checkout + + - run: + name: Compute vars + command: | + echo 'export IMAGE="acme/backend:${CIRCLE_SHA1}"' >> $BASH_ENV + echo 'export SBOM_FILE="$(echo acme/backend:${CIRCLE_SHA1} | tr "/:+" "__")-$(date -u +%Y%m%dT%H%M%SZ).sbom.json"' >> $BASH_ENV + - run: + name: Build image + SBOM (Option A) + command: | + docker build \ + --build-arg STELLA_SBOM_BUILDER="$STELLA_URL/registry/stella-sbom-builder:latest" \ + --build-arg SBOM_FILE="$SBOM_FILE" \ + -t "$IMAGE" . + # --- Option B fallback (when you must keep the existing build step as‑is) --- + #- run: + # name: SBOM builder (Option B) + # command: | + # docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ + # -v "$PWD:/workspace" \ + # "$STELLA_URL/registry/stella-sbom-builder:latest" \ + # build --image "$IMAGE" --output "/workspace/${SBOM_FILE}" + - run: + name: Scan + command: | + docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ + -v "$PWD/${SBOM_FILE}:/${SBOM_FILE}:ro" \ + -e STELLA_OPS_URL="https://$STELLA_URL" \ + "$STELLA_URL/registry/stella-cli:latest" \ + scan --sbom "/${SBOM_FILE}" "$IMAGE" +workflows: + stella: + jobs: [stella_scan] +``` + +--- + +### 3.3 Gitea Actions `.gitea/workflows/stella.yml` + +*(Gitea 1.22+ ships native Actions compatible with GitHub syntax)* + +```yaml +name: Stella Scan +on: [push] + +jobs: + stella: + runs-on: ubuntu-latest + env: + STELLA_URL: ${{ secrets.STELLA_URL }} + DOCKER_HOST: tcp://docker:2375 # provided by the docker:dind service + services: + docker: + image: docker:dind + options: >- + --privileged + steps: + - uses: actions/checkout@v4 + + - name: Compute vars + id: vars + run: | + echo "IMAGE=ghcr.io/${{ gitea.repository }}:${{ gitea.sha }}" >> $GITEA_OUTPUT + echo "SBOM_FILE=$(echo ghcr.io/${{ gitea.repository }}:${{ gitea.sha }} | tr '/:+' '__')-$(date -u +%Y%m%dT%H%M%SZ).sbom.json" >> $GITEA_OUTPUT + + - name: Build image + SBOM (Option A) + run: | + docker build \ + --build-arg STELLA_SBOM_BUILDER="${STELLA_URL}/registry/stella-sbom-builder:latest" \ + --build-arg SBOM_FILE="${{ steps.vars.outputs.SBOM_FILE }}" \ + -t "${{ steps.vars.outputs.IMAGE }}" . + + # --- Option B fallback (when you must keep the existing build step as‑is) --- + #- name: SBOM builder (Option B) + # run: | + # docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ + # -v "$(pwd):/workspace" \ + # "${STELLA_URL}/registry/stella-sbom-builder:latest" \ + # build --image "${{ steps.vars.outputs.IMAGE }}" --output "/workspace/${{ steps.vars.outputs.SBOM_FILE }}" + + - name: Scan + run: | + docker run --rm -e DOCKER_HOST="$DOCKER_HOST" \ + -v "$(pwd)/${{ steps.vars.outputs.SBOM_FILE }}:/${{ steps.vars.outputs.SBOM_FILE }}:ro" \ + -e STELLA_OPS_URL="https://${STELLA_URL}" \ + "${STELLA_URL}/registry/stella-cli:latest" \ + scan --sbom "/${{ steps.vars.outputs.SBOM_FILE }}" "${{ steps.vars.outputs.IMAGE }}" +``` + +--- + ## 4 · Docs CI (Gitea Actions & Offline Mirror) StellaOps ships a dedicated Docs workflow at `.gitea/workflows/docs.yml`. When mirroring the pipeline offline or running it locally, install the same toolchain so markdown linting, schema validation, and HTML preview stay deterministic. @@ -305,7 +305,7 @@ Policy Engine v2 pipelines now fail fast if policy documents are malformed. Afte ```bash dotnet run \ - --project tools/PolicyDslValidator/PolicyDslValidator.csproj \ + --project src/Tools/PolicyDslValidator/PolicyDslValidator.csproj \ -- \ --strict docs/examples/policies/*.yaml ``` @@ -322,7 +322,7 @@ Catch unexpected policy regressions by exercising a small set of golden SBOM fin ```bash dotnet run \ - --project tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj \ + --project src/Tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj \ -- \ --scenario-root samples/policy/simulations \ --output artifacts/policy-simulations @@ -336,17 +336,17 @@ dotnet run \ --- ## 5 · Troubleshooting cheat‑sheet - -| Symptom | Root cause | First things to try | -| ------------------------------------- | --------------------------- | --------------------------------------------------------------- | -| `no such host $STELLA_URL` | DNS typo or VPN outage | `ping $STELLA_URL` from runner | -| `connection refused` when CLI uploads | Port 443 blocked | open firewall / check ingress | -| `failed to stat /.json` | SBOM wasn’t produced | Did Option A actually run builder? If not, enable Option B | -| `registry unauthorized` | Runner lacks registry creds | `docker login $STELLA_URL/registry` (store creds in CI secrets) | -| Non‑zero scan exit | Blocking vuln/licence | Open project in Ops UI → triage or waive | - ---- - + +| Symptom | Root cause | First things to try | +| ------------------------------------- | --------------------------- | --------------------------------------------------------------- | +| `no such host $STELLA_URL` | DNS typo or VPN outage | `ping $STELLA_URL` from runner | +| `connection refused` when CLI uploads | Port 443 blocked | open firewall / check ingress | +| `failed to stat /.json` | SBOM wasn’t produced | Did Option A actually run builder? If not, enable Option B | +| `registry unauthorized` | Runner lacks registry creds | `docker login $STELLA_URL/registry` (store creds in CI secrets) | +| Non‑zero scan exit | Blocking vuln/licence | Open project in Ops UI → triage or waive | + +--- + ### Change log * **2025‑10‑18** – Documented Docs CI toolchain (Ajv validation, static preview) and offline checklist. diff --git a/docs/modules/cli/AGENTS.md b/docs/modules/cli/AGENTS.md new file mode 100644 index 00000000..769da4d7 --- /dev/null +++ b/docs/modules/cli/AGENTS.md @@ -0,0 +1,22 @@ +# CLI agent guide + +## Mission +The `stella` CLI is the operator-facing Swiss army knife for scans, exports, policy management, offline kit operations, and automation scripting. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/cli/README.md b/docs/modules/cli/README.md new file mode 100644 index 00000000..ee7f1089 --- /dev/null +++ b/docs/modules/cli/README.md @@ -0,0 +1,40 @@ +# StellaOps CLI + +The `stella` CLI is the operator-facing Swiss army knife for scans, exports, policy management, offline kit operations, and automation scripting. + +## Responsibilities +- Deliver deterministic verbs for scan, diff, export, policy, and observability operations. +- Handle interactive and non-interactive authentication via Authority (device code, client credentials). +- Support offline kit workflows including bundle verification and seed installation. +- Expose JSON outputs suitable for CI parity and golden tests. + +## Key components +- `StellaOps.Cli` native AOT host. +- Shared helpers in `StellaOps.Cli.Core`. +- Restart-time plug-ins under `StellaOps.Cli.Plugins.*`. + +## Integrations & dependencies +- Authority for token exchange. +- Backend APIs (Scanner, Policy, Export Center, Notify). +- Offline kit bundles and local keychain/DPoP storage. + +## Operational notes +- Deterministic output fixtures under `src/Cli/StellaOps.Cli.Tests`. +- Versioned command docs in `docs/modules/cli/guides`. +- Plugin catalogue in `plugins/cli/**` (restart-only). + +## Related resources +- ./guides/20_REFERENCE.md +- ./guides/cli-reference.md +- ./guides/policy.md + +## Backlog references +- DOCS-CLI-OBS-52-001 / DOCS-CLI-FORENSICS-53-001 in ../../TASKS.md. +- CLI-CORE-41-001 epic in `src/Cli/StellaOps.Cli/TASKS.md`. + +## Epic alignment +- **Epic 2 – Policy Engine & Editor:** deliver deterministic policy authoring, simulation, and explain verbs. +- **Epic 4 – Policy Studio:** integrate registry/promotion workflows, approvals, and lint tooling. +- **Epic 6 – Vulnerability Explorer:** surface triage and ledger operations. +- **Epic 10 – Export Center:** orchestrate export requests, verification, and Offline Kit automation. +- **Epic 11 – Notifications Studio:** manage notification authoring/previews from the command line. diff --git a/docs/modules/cli/TASKS.md b/docs/modules/cli/TASKS.md new file mode 100644 index 00000000..5f85becd --- /dev/null +++ b/docs/modules/cli/TASKS.md @@ -0,0 +1,9 @@ +# Task board — CLI + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| CLI-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| CLI-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| CLI-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_CLI.md b/docs/modules/cli/architecture.md similarity index 96% rename from docs/ARCHITECTURE_CLI.md rename to docs/modules/cli/architecture.md index fccf3c3c..4caacc4b 100644 --- a/docs/ARCHITECTURE_CLI.md +++ b/docs/modules/cli/architecture.md @@ -1,4 +1,6 @@ -# component_architecture_cli.md — **Stella Ops CLI** (2025Q4) +# component_architecture_cli.md — **Stella Ops CLI** (2025Q4) + +> Consolidates requirements captured in the Policy Engine, Policy Studio, Vulnerability Explorer, Export Center, and Notifications implementation plans and module guides. > **Scope.** Implementation‑ready architecture for **Stella Ops CLI**: command surface, process model, auth (Authority/DPoP), integration with Scanner/Excititor/Concelier/Signer/Attestor, Buildx plug‑in management, offline kit behavior, packaging, observability, security posture, and CI ergonomics. diff --git a/docs/cli/20_REFERENCE.md b/docs/modules/cli/guides/20_REFERENCE.md similarity index 78% rename from docs/cli/20_REFERENCE.md rename to docs/modules/cli/guides/20_REFERENCE.md index 941aa692..dbc092af 100755 --- a/docs/cli/20_REFERENCE.md +++ b/docs/modules/cli/guides/20_REFERENCE.md @@ -1,8 +1,8 @@ -# CLI Reference (`stella --help`) - -> **Auto‑generated file — do not edit manually.** -> On every tagged release the CI pipeline runs -> `stella --help --markdown > docs/cli/20_REFERENCE.md` -> ensuring this document always matches the shipped binary. - -*(The reference will appear after the first public α release.)* +# CLI Reference (`stella --help`) + +> **Auto‑generated file — do not edit manually.** +> On every tagged release the CI pipeline runs +> `stella --help --markdown > docs/modules/cli/guides/20_REFERENCE.md` +> ensuring this document always matches the shipped binary. + +*(The reference will appear after the first public α release.)* diff --git a/docs/cli/cli-reference.md b/docs/modules/cli/guides/cli-reference.md similarity index 93% rename from docs/cli/cli-reference.md rename to docs/modules/cli/guides/cli-reference.md index 1f88de91..c1515685 100644 --- a/docs/cli/cli-reference.md +++ b/docs/modules/cli/guides/cli-reference.md @@ -1,316 +1,316 @@ -# CLI AOC Commands Reference - -> **Audience:** DevEx engineers, operators, and CI authors integrating the `stella` CLI with Aggregation-Only Contract (AOC) workflows. -> **Scope:** Command synopsis, options, exit codes, and offline considerations for `stella sources ingest --dry-run` and `stella aoc verify` as introduced in Sprint 19. - -Both commands are designed to enforce the AOC guardrails documented in the [aggregation-only reference](../ingestion/aggregation-only-contract.md) and the [architecture overview](../architecture/overview.md). They consume Authority-issued tokens with tenant scopes and never mutate ingestion stores. - ---- - -## 1 · Prerequisites - -- CLI version: `stella` ≥ 0.19.0 (AOC feature gate enabled). -- Required scopes (DPoP-bound): - - `advisory:read` for Concelier sources. - - `vex:read` for Excititor sources (optional but required for VEX checks). - - `aoc:verify` to invoke guard verification endpoints. - - `tenant:select` if your deployment uses tenant switching. -- Connectivity: direct access to Concelier/Excititor APIs or Offline Kit snapshot (see § 4). -- Environment: set `STELLA_AUTHORITY_URL`, `STELLA_TENANT`, and export a valid OpTok via `stella auth login` or existing token cache. - ---- - -## 2 · `stella sources ingest --dry-run` - -### 2.1 Synopsis - -```bash -stella sources ingest --dry-run \ - --source \ - --input \ - [--tenant ] \ - [--format json|table] \ - [--no-color] \ - [--output ] -``` - -### 2.2 Description - -Previews an ingestion write without touching MongoDB. The command loads an upstream advisory or VEX document, computes the would-write payload, runs it through the `AOCWriteGuard`, and reports any forbidden fields, provenance gaps, or idempotency issues. Use it during connector development, CI validation, or while triaging incidents. - -### 2.3 Options - -| Option | Description | -|--------|-------------| -| `--source ` | Logical source name (`redhat`, `ubuntu`, `osv`, etc.). Mirrors connector configuration. | -| `--input ` | Path to local CSAF/OSV/VEX file or HTTPS URI. CLI normalises transport (gzip/base64) before guard evaluation. | -| `--tenant ` | Overrides default tenant for multi-tenant deployments. Mandatory when `STELLA_TENANT` is not set. | -| `--format json|table` | Output format. `table` (default) prints summary with highlighted violations; `json` emits machine-readable report (see below). | -| `--no-color` | Disables ANSI colour output for CI logs. | -| `--output ` | Writes the JSON report to file while still printing human-readable summary to stdout. | - -### 2.4 Output schema (JSON) - -```json -{ - "source": "redhat", - "tenant": "default", - "guardVersion": "1.0.0", - "status": "ok", - "document": { - "contentHash": "sha256:…", - "supersedes": null, - "provenance": { - "signature": { "format": "pgp", "present": true } - } - }, - "violations": [] -} -``` - -When violations exist, `status` becomes `error` and `violations` contains entries with `code` (`ERR_AOC_00x`), a short `message`, and JSON Pointer `path` values indicating offending fields. - -### 2.5 Exit codes - -| Exit code | Meaning | -|-----------|---------| -| `0` | Guard passed; would-write payload is AOC compliant. | -| `11` | `ERR_AOC_001` – Forbidden field (`severity`, `cvss`, etc.) detected. | -| `12` | `ERR_AOC_002` – Merge attempt (multiple upstream sources fused). | -| `13` | `ERR_AOC_003` – Idempotency violation (duplicate without supersedes). | -| `14` | `ERR_AOC_004` – Missing provenance fields. | -| `15` | `ERR_AOC_005` – Signature/checksum mismatch. | -| `16` | `ERR_AOC_006` – Effective findings present (Policy-only data). | -| `17` | `ERR_AOC_007` – Unknown top-level fields / schema violation. | -| `70` | Transport error (network, auth, malformed input). | - -> Exit codes map directly to the `ERR_AOC_00x` table for scripting consistency. Multiple violations yield the highest-priority code (e.g., 11 takes precedence over 14). - -### 2.6 Examples - -Dry-run a local CSAF file: - -```bash -stella sources ingest --dry-run \ - --source redhat \ - --input ./fixtures/redhat/RHSA-2025-1234.json -``` - -Stream from HTTPS and emit JSON for CI: - -```bash -stella sources ingest --dry-run \ - --source osv \ - --input https://osv.dev/vulnerability/GHSA-aaaa-bbbb \ - --format json \ - --output artifacts/osv-dry-run.json - -cat artifacts/osv-dry-run.json | jq '.violations' -``` - -### 2.7 Offline notes - -When operating in sealed/offline mode: - -- Use `--input` paths pointing to Offline Kit snapshots (`offline-kit/advisories/*.json`). -- Provide `--tenant` explicitly if the offline bundle contains multiple tenants. -- The command does not attempt network access when given a file path. -- Store reports with `--output` to include in transfer packages for policy review. - ---- - -## 3 · `stella aoc verify` - -### 3.1 Synopsis - -```bash -stella aoc verify \ - [--since ] \ - [--limit ] \ - [--sources ] \ - [--codes ] \ - [--format table|json] \ - [--export ] \ - [--tenant ] \ - [--no-color] -``` - -### 3.2 Description - -Replays the AOC guard against stored raw documents. By default it checks all advisories and VEX statements ingested in the last 24 hours for the active tenant, reporting totals, top violation codes, and sample documents. Use it in CI pipelines, scheduled verifications, or during incident response. - -### 3.3 Options - -| Option | Description | -|--------|-------------| -| `--since ` | Verification window. Accepts ISO 8601 timestamp (`2025-10-25T12:00:00Z`) or duration (`48h`, `7d`). Defaults to `24h`. | -| `--limit ` | Maximum number of violations to display (per code). `0` means show all. Defaults to `20`. | -| `--sources ` | Comma-separated list of sources (`redhat,ubuntu,osv`). Filters both advisories and VEX entries. | -| `--codes ` | Restricts output to specific `ERR_AOC_00x` codes. Useful for regression tracking. | -| `--format table|json` | `table` (default) prints summary plus top violations; `json` outputs machine-readable report identical to the `/aoc/verify` API. | -| `--export ` | Writes the JSON report to disk (useful for audits/offline uploads). | -| `--tenant ` | Overrides tenant context. Required for cross-tenant verifications when run by platform operators. | -| `--no-color` | Disables ANSI colours. | - -`table` mode prints a summary showing the active tenant, evaluated window, counts of checked advisories/VEX statements, the active limit, total writes/violations, and whether the page was truncated. Status is colour-coded as `ok`, `violations`, or `truncated`. When violations exist the detail table lists the code, total occurrences, first sample document (`source` + `documentId` + `contentHash`), and JSON pointer path. - -### 3.4 Report structure (JSON) - -```json -{ - "tenant": "default", - "window": { - "from": "2025-10-25T12:00:00Z", - "to": "2025-10-26T12:00:00Z" - }, - "checked": { - "advisories": 482, - "vex": 75 - }, - "violations": [ - { - "code": "ERR_AOC_001", - "count": 2, - "examples": [ - { - "source": "redhat", - "documentId": "advisory_raw:redhat:RHSA-2025:1", - "contentHash": "sha256:…", - "path": "/content/raw/cvss" - } - ] - } - ], - "metrics": { - "ingestion_write_total": 557, - "aoc_violation_total": 2 - }, - "truncated": false -} -``` - -### 3.5 Exit codes - -| Exit code | Meaning | -|-----------|---------| -| `0` | Verification succeeded with zero violations. | -| `11…17` | Same mapping as § 2.5 when violations are detected. Highest-priority code returned. | -| `18` | Verification ran but results truncated (limit reached) – treat as warning; rerun with higher `--limit`. | -| `70` | Transport/authentication error. | -| `71` | CLI misconfiguration (missing tenant, invalid `--since`, etc.). | - -### 3.6 Examples - -Daily verification across all sources: - -```bash -stella aoc verify --since 24h --format table -``` - -CI pipeline focusing on errant sources and exporting evidence: - -```bash -stella aoc verify \ - --sources redhat,ubuntu \ - --codes ERR_AOC_001,ERR_AOC_004 \ - --format json \ - --limit 100 \ - --export artifacts/aoc-verify.json - -jq '.violations[] | {code, count}' artifacts/aoc-verify.json -``` - -Air-gapped verification using Offline Kit snapshot (example script): - -```bash -stella aoc verify \ - --since 7d \ - --format json \ - --export /mnt/offline/aoc-verify-$(date +%F).json - -sha256sum /mnt/offline/aoc-verify-*.json > /mnt/offline/checksums.txt -``` - -### 3.7 Automation tips - -- Schedule with `cron` or platform scheduler and fail the job when exit code ≥ 11. -- Pair with `stella sources ingest --dry-run` for pre-flight validation before re-enabling a paused source. -- Push JSON exports to observability pipelines for historical tracking of violation counts. - -### 3.8 Offline notes - -- Works against Offline Kit Mongo snapshots when CLI is pointed at the local API gateway included in the bundle. -- When fully disconnected, run against exported `aoc verify` reports generated on production and replay them using `--format json --export` (automation recipe above). -- Include verification output in compliance packages alongside Offline Kit manifests. - ---- - -## 4 · Global exit-code reference - -| Code | Summary | -|------|---------| -| `0` | Success / no violations. | -| `11` | `ERR_AOC_001` – Forbidden field present. | -| `12` | `ERR_AOC_002` – Merge attempt detected. | -| `13` | `ERR_AOC_003` – Idempotency violation. | -| `14` | `ERR_AOC_004` – Missing provenance/signature metadata. | -| `15` | `ERR_AOC_005` – Signature/checksum mismatch. | -| `16` | `ERR_AOC_006` – Effective findings in ingestion payload. | -| `17` | `ERR_AOC_007` – Schema violation / unknown fields. | -| `18` | Partial verification (limit reached). | -| `70` | Transport or HTTP failure. | -| `71` | CLI usage error (invalid arguments, missing tenant). | - -Use these codes in CI to map outcomes to build statuses or alert severities. - ---- - -## 4 · `stella vuln observations` (Overlay paging) - -`stella vuln observations` lists raw advisory observations for downstream overlays (Graph Explorer, Policy simulations, Console). Large tenants can now page through results deterministically. - -| Option | Description | -|--------|-------------| -| `--limit ` | Caps the number of observations returned in a single call. Defaults to `200`; values above `500` are clamped server-side. | -| `--cursor ` | Opaque continuation token produced by the previous page (`nextCursor` in JSON output). Pass it back to resume iteration. | - -Additional notes: - -- Table mode prints a hint when `hasMore` is `true`: - `[yellow]More observations available. Continue with --cursor [/]`. -- JSON mode returns `nextCursor` and `hasMore` alongside the observation list so automation can loop until `hasMore` is `false`. -- Supplying a non-positive limit falls back to the default (`200`). Invalid/expired cursors yield `400 Bad Request`; restart without `--cursor` to begin a fresh iteration. - ---- - -## 5 · Related references - -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) -- [Architecture overview](../architecture/overview.md) -- [Console AOC dashboard](../ui/console.md) -- [Authority scopes](../ARCHITECTURE_AUTHORITY.md) - ---- - -## 6 · Compliance checklist - -- [ ] Usage documented for both table and JSON formats. -- [ ] Exit-code mapping matches `ERR_AOC_00x` definitions and automation guidance. -- [ ] Offline/air-gap workflow captured for both commands. -- [ ] References to AOC architecture and console docs included. -- [ ] Examples validated against current CLI syntax (update post-implementation). -- [ ] Docs guild screenshot/narrative placeholder logged for release notes (pending CLI team capture). - ---- - -*Last updated: 2025-10-29 (Sprint 24).* - -## 13. Authority configuration quick reference - -| Setting | Purpose | How to set | -|---------|---------|------------| -| `StellaOps:Authority:OperatorReason` | Incident/change description recorded with `orch:operate` tokens. | CLI flag `--Authority:OperatorReason=...` or env `STELLAOPS_ORCH_REASON`. | -| `StellaOps:Authority:OperatorTicket` | Change/incident ticket reference paired with orchestrator control actions. | CLI flag `--Authority:OperatorTicket=...` or env `STELLAOPS_ORCH_TICKET`. | - -> Tokens requesting `orch:operate` will fail with `invalid_request` unless both values are present. Choose concise strings (≤256 chars for reason, ≤128 chars for ticket) and avoid sensitive data. - +# CLI AOC Commands Reference + +> **Audience:** DevEx engineers, operators, and CI authors integrating the `stella` CLI with Aggregation-Only Contract (AOC) workflows. +> **Scope:** Command synopsis, options, exit codes, and offline considerations for `stella sources ingest --dry-run` and `stella aoc verify` as introduced in Sprint 19. + +Both commands are designed to enforce the AOC guardrails documented in the [aggregation-only reference](../../ingestion/aggregation-only-contract.md) and the [architecture overview](../../platform/architecture-overview.md). They consume Authority-issued tokens with tenant scopes and never mutate ingestion stores. + +--- + +## 1 · Prerequisites + +- CLI version: `stella` ≥ 0.19.0 (AOC feature gate enabled). +- Required scopes (DPoP-bound): + - `advisory:read` for Concelier sources. + - `vex:read` for Excititor sources (optional but required for VEX checks). + - `aoc:verify` to invoke guard verification endpoints. + - `tenant:select` if your deployment uses tenant switching. +- Connectivity: direct access to Concelier/Excititor APIs or Offline Kit snapshot (see § 4). +- Environment: set `STELLA_AUTHORITY_URL`, `STELLA_TENANT`, and export a valid OpTok via `stella auth login` or existing token cache. + +--- + +## 2 · `stella sources ingest --dry-run` + +### 2.1 Synopsis + +```bash +stella sources ingest --dry-run \ + --source \ + --input \ + [--tenant ] \ + [--format json|table] \ + [--no-color] \ + [--output ] +``` + +### 2.2 Description + +Previews an ingestion write without touching MongoDB. The command loads an upstream advisory or VEX document, computes the would-write payload, runs it through the `AOCWriteGuard`, and reports any forbidden fields, provenance gaps, or idempotency issues. Use it during connector development, CI validation, or while triaging incidents. + +### 2.3 Options + +| Option | Description | +|--------|-------------| +| `--source ` | Logical source name (`redhat`, `ubuntu`, `osv`, etc.). Mirrors connector configuration. | +| `--input ` | Path to local CSAF/OSV/VEX file or HTTPS URI. CLI normalises transport (gzip/base64) before guard evaluation. | +| `--tenant ` | Overrides default tenant for multi-tenant deployments. Mandatory when `STELLA_TENANT` is not set. | +| `--format json|table` | Output format. `table` (default) prints summary with highlighted violations; `json` emits machine-readable report (see below). | +| `--no-color` | Disables ANSI colour output for CI logs. | +| `--output ` | Writes the JSON report to file while still printing human-readable summary to stdout. | + +### 2.4 Output schema (JSON) + +```json +{ + "source": "redhat", + "tenant": "default", + "guardVersion": "1.0.0", + "status": "ok", + "document": { + "contentHash": "sha256:…", + "supersedes": null, + "provenance": { + "signature": { "format": "pgp", "present": true } + } + }, + "violations": [] +} +``` + +When violations exist, `status` becomes `error` and `violations` contains entries with `code` (`ERR_AOC_00x`), a short `message`, and JSON Pointer `path` values indicating offending fields. + +### 2.5 Exit codes + +| Exit code | Meaning | +|-----------|---------| +| `0` | Guard passed; would-write payload is AOC compliant. | +| `11` | `ERR_AOC_001` – Forbidden field (`severity`, `cvss`, etc.) detected. | +| `12` | `ERR_AOC_002` – Merge attempt (multiple upstream sources fused). | +| `13` | `ERR_AOC_003` – Idempotency violation (duplicate without supersedes). | +| `14` | `ERR_AOC_004` – Missing provenance fields. | +| `15` | `ERR_AOC_005` – Signature/checksum mismatch. | +| `16` | `ERR_AOC_006` – Effective findings present (Policy-only data). | +| `17` | `ERR_AOC_007` – Unknown top-level fields / schema violation. | +| `70` | Transport error (network, auth, malformed input). | + +> Exit codes map directly to the `ERR_AOC_00x` table for scripting consistency. Multiple violations yield the highest-priority code (e.g., 11 takes precedence over 14). + +### 2.6 Examples + +Dry-run a local CSAF file: + +```bash +stella sources ingest --dry-run \ + --source redhat \ + --input ./fixtures/redhat/RHSA-2025-1234.json +``` + +Stream from HTTPS and emit JSON for CI: + +```bash +stella sources ingest --dry-run \ + --source osv \ + --input https://osv.dev/vulnerability/GHSA-aaaa-bbbb \ + --format json \ + --output artifacts/osv-dry-run.json + +cat artifacts/osv-dry-run.json | jq '.violations' +``` + +### 2.7 Offline notes + +When operating in sealed/offline mode: + +- Use `--input` paths pointing to Offline Kit snapshots (`offline-kit/advisories/*.json`). +- Provide `--tenant` explicitly if the offline bundle contains multiple tenants. +- The command does not attempt network access when given a file path. +- Store reports with `--output` to include in transfer packages for policy review. + +--- + +## 3 · `stella aoc verify` + +### 3.1 Synopsis + +```bash +stella aoc verify \ + [--since ] \ + [--limit ] \ + [--sources ] \ + [--codes ] \ + [--format table|json] \ + [--export ] \ + [--tenant ] \ + [--no-color] +``` + +### 3.2 Description + +Replays the AOC guard against stored raw documents. By default it checks all advisories and VEX statements ingested in the last 24 hours for the active tenant, reporting totals, top violation codes, and sample documents. Use it in CI pipelines, scheduled verifications, or during incident response. + +### 3.3 Options + +| Option | Description | +|--------|-------------| +| `--since ` | Verification window. Accepts ISO 8601 timestamp (`2025-10-25T12:00:00Z`) or duration (`48h`, `7d`). Defaults to `24h`. | +| `--limit ` | Maximum number of violations to display (per code). `0` means show all. Defaults to `20`. | +| `--sources ` | Comma-separated list of sources (`redhat,ubuntu,osv`). Filters both advisories and VEX entries. | +| `--codes ` | Restricts output to specific `ERR_AOC_00x` codes. Useful for regression tracking. | +| `--format table|json` | `table` (default) prints summary plus top violations; `json` outputs machine-readable report identical to the `/aoc/verify` API. | +| `--export ` | Writes the JSON report to disk (useful for audits/offline uploads). | +| `--tenant ` | Overrides tenant context. Required for cross-tenant verifications when run by platform operators. | +| `--no-color` | Disables ANSI colours. | + +`table` mode prints a summary showing the active tenant, evaluated window, counts of checked advisories/VEX statements, the active limit, total writes/violations, and whether the page was truncated. Status is colour-coded as `ok`, `violations`, or `truncated`. When violations exist the detail table lists the code, total occurrences, first sample document (`source` + `documentId` + `contentHash`), and JSON pointer path. + +### 3.4 Report structure (JSON) + +```json +{ + "tenant": "default", + "window": { + "from": "2025-10-25T12:00:00Z", + "to": "2025-10-26T12:00:00Z" + }, + "checked": { + "advisories": 482, + "vex": 75 + }, + "violations": [ + { + "code": "ERR_AOC_001", + "count": 2, + "examples": [ + { + "source": "redhat", + "documentId": "advisory_raw:redhat:RHSA-2025:1", + "contentHash": "sha256:…", + "path": "/content/raw/cvss" + } + ] + } + ], + "metrics": { + "ingestion_write_total": 557, + "aoc_violation_total": 2 + }, + "truncated": false +} +``` + +### 3.5 Exit codes + +| Exit code | Meaning | +|-----------|---------| +| `0` | Verification succeeded with zero violations. | +| `11…17` | Same mapping as § 2.5 when violations are detected. Highest-priority code returned. | +| `18` | Verification ran but results truncated (limit reached) – treat as warning; rerun with higher `--limit`. | +| `70` | Transport/authentication error. | +| `71` | CLI misconfiguration (missing tenant, invalid `--since`, etc.). | + +### 3.6 Examples + +Daily verification across all sources: + +```bash +stella aoc verify --since 24h --format table +``` + +CI pipeline focusing on errant sources and exporting evidence: + +```bash +stella aoc verify \ + --sources redhat,ubuntu \ + --codes ERR_AOC_001,ERR_AOC_004 \ + --format json \ + --limit 100 \ + --export artifacts/aoc-verify.json + +jq '.violations[] | {code, count}' artifacts/aoc-verify.json +``` + +Air-gapped verification using Offline Kit snapshot (example script): + +```bash +stella aoc verify \ + --since 7d \ + --format json \ + --export /mnt/offline/aoc-verify-$(date +%F).json + +sha256sum /mnt/offline/aoc-verify-*.json > /mnt/offline/checksums.txt +``` + +### 3.7 Automation tips + +- Schedule with `cron` or platform scheduler and fail the job when exit code ≥ 11. +- Pair with `stella sources ingest --dry-run` for pre-flight validation before re-enabling a paused source. +- Push JSON exports to observability pipelines for historical tracking of violation counts. + +### 3.8 Offline notes + +- Works against Offline Kit Mongo snapshots when CLI is pointed at the local API gateway included in the bundle. +- When fully disconnected, run against exported `aoc verify` reports generated on production and replay them using `--format json --export` (automation recipe above). +- Include verification output in compliance packages alongside Offline Kit manifests. + +--- + +## 4 · Global exit-code reference + +| Code | Summary | +|------|---------| +| `0` | Success / no violations. | +| `11` | `ERR_AOC_001` – Forbidden field present. | +| `12` | `ERR_AOC_002` – Merge attempt detected. | +| `13` | `ERR_AOC_003` – Idempotency violation. | +| `14` | `ERR_AOC_004` – Missing provenance/signature metadata. | +| `15` | `ERR_AOC_005` – Signature/checksum mismatch. | +| `16` | `ERR_AOC_006` – Effective findings in ingestion payload. | +| `17` | `ERR_AOC_007` – Schema violation / unknown fields. | +| `18` | Partial verification (limit reached). | +| `70` | Transport or HTTP failure. | +| `71` | CLI usage error (invalid arguments, missing tenant). | + +Use these codes in CI to map outcomes to build statuses or alert severities. + +--- + +## 4 · `stella vuln observations` (Overlay paging) + +`stella vuln observations` lists raw advisory observations for downstream overlays (Graph Explorer, Policy simulations, Console). Large tenants can now page through results deterministically. + +| Option | Description | +|--------|-------------| +| `--limit ` | Caps the number of observations returned in a single call. Defaults to `200`; values above `500` are clamped server-side. | +| `--cursor ` | Opaque continuation token produced by the previous page (`nextCursor` in JSON output). Pass it back to resume iteration. | + +Additional notes: + +- Table mode prints a hint when `hasMore` is `true`: + `[yellow]More observations available. Continue with --cursor [/]`. +- JSON mode returns `nextCursor` and `hasMore` alongside the observation list so automation can loop until `hasMore` is `false`. +- Supplying a non-positive limit falls back to the default (`200`). Invalid/expired cursors yield `400 Bad Request`; restart without `--cursor` to begin a fresh iteration. + +--- + +## 5 · Related references + +- [Aggregation-Only Contract reference](../../ingestion/aggregation-only-contract.md) +- [Architecture overview](../../platform/architecture-overview.md) +- [Console AOC dashboard](../../ui/console.md) +- [Authority scopes](../../authority/architecture.md) + +--- + +## 6 · Compliance checklist + +- [ ] Usage documented for both table and JSON formats. +- [ ] Exit-code mapping matches `ERR_AOC_00x` definitions and automation guidance. +- [ ] Offline/air-gap workflow captured for both commands. +- [ ] References to AOC architecture and console docs included. +- [ ] Examples validated against current CLI syntax (update post-implementation). +- [ ] Docs guild screenshot/narrative placeholder logged for release notes (pending CLI team capture). + +--- + +*Last updated: 2025-10-29 (Sprint 24).* + +## 13. Authority configuration quick reference + +| Setting | Purpose | How to set | +|---------|---------|------------| +| `StellaOps:Authority:OperatorReason` | Incident/change description recorded with `orch:operate` tokens. | CLI flag `--Authority:OperatorReason=...` or env `STELLAOPS_ORCH_REASON`. | +| `StellaOps:Authority:OperatorTicket` | Change/incident ticket reference paired with orchestrator control actions. | CLI flag `--Authority:OperatorTicket=...` or env `STELLAOPS_ORCH_TICKET`. | + +> Tokens requesting `orch:operate` will fail with `invalid_request` unless both values are present. Choose concise strings (≤256 chars for reason, ≤128 chars for ticket) and avoid sensitive data. + diff --git a/docs/cli/policy.md b/docs/modules/cli/guides/policy.md similarity index 100% rename from docs/cli/policy.md rename to docs/modules/cli/guides/policy.md diff --git a/docs/modules/cli/implementation_plan.md b/docs/modules/cli/implementation_plan.md new file mode 100644 index 00000000..9a45c60b --- /dev/null +++ b/docs/modules/cli/implementation_plan.md @@ -0,0 +1,23 @@ +# Implementation plan — CLI + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 2 – Policy Engine & Editor:** deliver deterministic policy verbs, simulation, and explain outputs. +- **Epic 4 – Policy Studio:** add registry/promotion workflows, lint tooling, and approvals UX. +- **Epic 6 – Vulnerability Explorer:** integrate ledger/triage operations. +- **Epic 10 – Export Center:** automate export verification and Offline Kit flows. +- **Epic 11 – Notifications Studio:** manage rule/channel authoring and previews via CLI. +- Track CLI-specific work (e.g., CLI-CORE-41-001, DOCS-CLI-OBS-52-001) in ../../TASKS.md and src/Cli/**/TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/operations/cli-release-and-packaging.md b/docs/modules/cli/operations/release-and-packaging.md similarity index 94% rename from docs/operations/cli-release-and-packaging.md rename to docs/modules/cli/operations/release-and-packaging.md index 3176f22e..c8f137de 100644 --- a/docs/operations/cli-release-and-packaging.md +++ b/docs/modules/cli/operations/release-and-packaging.md @@ -1,134 +1,134 @@ -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -# CLI Release & Packaging Runbook - -This runbook describes how to build, sign, package, and distribute the StellaOps CLI with Task Pack support. It covers connected and air-gapped workflows, SBOM generation, parity gating, and distribution artifacts required by Sprint 43 (`DEVOPS-CLI-43-001`, `DEPLOY-PACKS-43-001`). - ---- - -## 1 · Release Artifacts - -| Artifact | Description | Notes | -|----------|-------------|-------| -| `stella--linux-x64.tar.gz` | Linux binary + completions | Includes man pages, localization files. | -| `stella--macos-universal.tar.gz` | macOS universal binary | Signed/notarized where applicable. | -| `stella--windows-x64.zip` | Windows binary + PowerShell modules | Code-signed. | -| `stella-cli-container:` | OCI image with CLI + pack runtime | Deterministic rootfs (scratch/distroless). | -| SBOM (`.cdx.json`) | CycloneDX SBOM per artifact | Generated via `stella sbom generate` or `syft`. | -| Checksums (`SHA256SUMS`) | Aggregated digest list | Signed with cosign. | -| Provenance (`.intoto.jsonl`) | DSSE attestation (SLSA L2) | Contains build metadata. | -| Release notes | Markdown summary | Links to task packs docs, parity matrix. | - ---- - -## 2 · Build Pipeline - -1. **Source checkout** – pinned commit, reproducible environment (Docker). -2. **Dependency lock** – `dotnet restore`, `npm ci` (for CLI frontends), ensure deterministic build flags. -3. **Build binaries** – cross-platform targets with reproducible timestamps. -4. **Run tests** – unit + integration; include `stella pack` commands (plan/run/verify) in CI. -5. **Generate SBOM** – `syft packages dist/stella-linux-x64 --output cyclonedx-json`. -6. **Bundle** – compress artifacts, include completions (`bash`, `zsh`, `fish`, PowerShell). -7. **Sign** – cosign signatures for binaries, checksums, container image. -8. **Publish** – upload to `downloads.stella-ops.org`, container registry, Packs Registry (for CLI container). -9. **Parity gating** – run CLI parity matrix tests vs Console features (automation in `DEVOPS-CLI-43-001`). - -CI must run in isolated environment (no network beyond allowlist). Cache dependencies for offline bundling. - ---- - -## 3 · Versioning & Channels - -- Semantic versioning (`YYYY.MM.patch`), e.g., `2025.10.0`. -- Channels: - - `edge` – nightly builds, limited support. - - `beta` – pre-release candidates. - - `stable` – production-ready, after parity gating. -- Release promotions mirror Task Pack channels; update downloads manifest (`deploy/downloads/manifest.json`). - ---- - -## 4 · Signing & Verification - -- Binaries signed with cosign (`cosign sign-blob`). -- Container image signed (`cosign sign stella-cli-container:`). -- DSSE provenance includes: - - Build pipeline ID. - - Source commit and repo. - - Dependencies SBOM digest. - - Test results summary. -- Verification command for operators: - -```bash -cosign verify-blob \ - --certificate-identity https://ci.stella-ops.org \ - --certificate-oidc-issuer https://fulcio.sigstore.dev \ - --signature stella-2025.10.0-linux-x64.sig \ - stella-2025.10.0-linux-x64.tar.gz -``` - ---- - -## 5 · Distribution - -### 5.1 Online - -- Publish artifacts to Downloads service; update manifest with digests, SBOM URLs, attestations. -- Update CLI parity docs (`docs/cli-vs-ui-parity.md`) and release notes. -- Push container image to registry with SBOM + attestations referenced as OCI referrers. -- Notify stakeholders via `#release-cli` channel and release mailing list. - -### 5.2 Offline / Air-Gap - -- Bundle CLI artifacts, Task Pack samples, and registry mirror: - -```bash -stella pack bundle export \ - --packs "sbom-remediation:1.3.0" \ - --output offline/packs-bundle-2025.10.0.tgz - -stella cli bundle export \ - --output offline/cli-2025.10.0.tgz \ - --include-container \ - --include-sbom -``` - -- Update Offline Kit manifest with new CLI version and pack bundle entries. -- Provide import scripts (`ouk import`) for sealed sites. - ---- - -## 6 · Parity Gating - -- `stella cli parity check` compares CLI commands vs parity matrix. -- CI fails release if any required command flagged `🟥` or `🟡` with severity > threshold. -- Parity report uploaded to Downloads workspace and linked in docs. -- Manual review required for new commands (ensure `man` pages and help text localized). - ---- - -## 7 · Localization & Documentation - -- CLI includes localization bundles; ensure `i18n.txz` packaged. -- Update man pages (`man/stella-pack.1`) and HTML docs. -- Sync docs: `docs/cli/overview.md`, pack authoring guide, release notes. -- Document new flags/commands in `docs/cli/commands/pack.md` (tracked in Sprint 42 tasks). - ---- - -## 8 · Release Checklist - -- [ ] All binaries built reproducibly (CI logs archived). -- [ ] Tests + parity matrix passing. -- [ ] SBOM + provenance generated and published. -- [ ] Cosign signatures created and verified. -- [ ] Downloads manifest updated (edge/beta/stable). -- [ ] Offline bundle exported and validated. -- [ ] Release notes + documentation updates merged. -- [ ] Notifications sent (chat/email). -- [ ] Imposed rule reminder present at top of document. - ---- - -*Last updated: 2025-10-27 (Sprint 43).* - +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +# CLI Release & Packaging Runbook + +This runbook describes how to build, sign, package, and distribute the StellaOps CLI with Task Pack support. It covers connected and air-gapped workflows, SBOM generation, parity gating, and distribution artifacts required by Sprint 43 (`DEVOPS-CLI-43-001`, `DEPLOY-PACKS-43-001`). + +--- + +## 1 · Release Artifacts + +| Artifact | Description | Notes | +|----------|-------------|-------| +| `stella--linux-x64.tar.gz` | Linux binary + completions | Includes man pages, localization files. | +| `stella--macos-universal.tar.gz` | macOS universal binary | Signed/notarized where applicable. | +| `stella--windows-x64.zip` | Windows binary + PowerShell modules | Code-signed. | +| `stella-cli-container:` | OCI image with CLI + pack runtime | Deterministic rootfs (scratch/distroless). | +| SBOM (`.cdx.json`) | CycloneDX SBOM per artifact | Generated via `stella sbom generate` or `syft`. | +| Checksums (`SHA256SUMS`) | Aggregated digest list | Signed with cosign. | +| Provenance (`.intoto.jsonl`) | DSSE attestation (SLSA L2) | Contains build metadata. | +| Release notes | Markdown summary | Links to task packs docs, parity matrix. | + +--- + +## 2 · Build Pipeline + +1. **Source checkout** – pinned commit, reproducible environment (Docker). +2. **Dependency lock** – `dotnet restore`, `npm ci` (for CLI frontends), ensure deterministic build flags. +3. **Build binaries** – cross-platform targets with reproducible timestamps. +4. **Run tests** – unit + integration; include `stella pack` commands (plan/run/verify) in CI. +5. **Generate SBOM** – `syft packages dist/stella-linux-x64 --output cyclonedx-json`. +6. **Bundle** – compress artifacts, include completions (`bash`, `zsh`, `fish`, PowerShell). +7. **Sign** – cosign signatures for binaries, checksums, container image. +8. **Publish** – upload to `downloads.stella-ops.org`, container registry, Packs Registry (for CLI container). +9. **Parity gating** – run CLI parity matrix tests vs Console features (automation in `DEVOPS-CLI-43-001`). + +CI must run in isolated environment (no network beyond allowlist). Cache dependencies for offline bundling. + +--- + +## 3 · Versioning & Channels + +- Semantic versioning (`YYYY.MM.patch`), e.g., `2025.10.0`. +- Channels: + - `edge` – nightly builds, limited support. + - `beta` – pre-release candidates. + - `stable` – production-ready, after parity gating. +- Release promotions mirror Task Pack channels; update downloads manifest (`deploy/downloads/manifest.json`). + +--- + +## 4 · Signing & Verification + +- Binaries signed with cosign (`cosign sign-blob`). +- Container image signed (`cosign sign stella-cli-container:`). +- DSSE provenance includes: + - Build pipeline ID. + - Source commit and repo. + - Dependencies SBOM digest. + - Test results summary. +- Verification command for operators: + +```bash +cosign verify-blob \ + --certificate-identity https://ci.stella-ops.org \ + --certificate-oidc-issuer https://fulcio.sigstore.dev \ + --signature stella-2025.10.0-linux-x64.sig \ + stella-2025.10.0-linux-x64.tar.gz +``` + +--- + +## 5 · Distribution + +### 5.1 Online + +- Publish artifacts to Downloads service; update manifest with digests, SBOM URLs, attestations. +- Update CLI parity docs (`docs/cli-vs-ui-parity.md`) and release notes. +- Push container image to registry with SBOM + attestations referenced as OCI referrers. +- Notify stakeholders via `#release-cli` channel and release mailing list. + +### 5.2 Offline / Air-Gap + +- Bundle CLI artifacts, Task Pack samples, and registry mirror: + +```bash +stella pack bundle export \ + --packs "sbom-remediation:1.3.0" \ + --output offline/packs-bundle-2025.10.0.tgz + +stella cli bundle export \ + --output offline/cli-2025.10.0.tgz \ + --include-container \ + --include-sbom +``` + +- Update Offline Kit manifest with new CLI version and pack bundle entries. +- Provide import scripts (`ouk import`) for sealed sites. + +--- + +## 6 · Parity Gating + +- `stella cli parity check` compares CLI commands vs parity matrix. +- CI fails release if any required command flagged `🟥` or `🟡` with severity > threshold. +- Parity report uploaded to Downloads workspace and linked in docs. +- Manual review required for new commands (ensure `man` pages and help text localized). + +--- + +## 7 · Localization & Documentation + +- CLI includes localization bundles; ensure `i18n.txz` packaged. +- Update man pages (`man/stella-pack.1`) and HTML docs. +- Sync docs: `docs/modules/cli/guides/overview.md`, pack authoring guide, release notes. +- Document new flags/commands in `docs/modules/cli/guides/commands/pack.md` (tracked in Sprint 42 tasks). + +--- + +## 8 · Release Checklist + +- [ ] All binaries built reproducibly (CI logs archived). +- [ ] Tests + parity matrix passing. +- [ ] SBOM + provenance generated and published. +- [ ] Cosign signatures created and verified. +- [ ] Downloads manifest updated (edge/beta/stable). +- [ ] Offline bundle exported and validated. +- [ ] Release notes + documentation updates merged. +- [ ] Notifications sent (chat/email). +- [ ] Imposed rule reminder present at top of document. + +--- + +*Last updated: 2025-10-27 (Sprint 43).* + diff --git a/docs/modules/concelier/AGENTS.md b/docs/modules/concelier/AGENTS.md new file mode 100644 index 00000000..d3526228 --- /dev/null +++ b/docs/modules/concelier/AGENTS.md @@ -0,0 +1,22 @@ +# Concelier agent guide + +## Mission +Concelier ingests signed advisories from dozens of sources and converts them into immutable observations plus linksets under the Aggregation-Only Contract (AOC). + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/concelier/README.md b/docs/modules/concelier/README.md new file mode 100644 index 00000000..5970f37d --- /dev/null +++ b/docs/modules/concelier/README.md @@ -0,0 +1,36 @@ +# StellaOps Concelier + +Concelier ingests signed advisories from dozens of sources and converts them into immutable observations plus linksets under the Aggregation-Only Contract (AOC). + +## Responsibilities +- Fetch and normalise vulnerability advisories via restart-time connectors. +- Persist observations and correlation linksets without precedence decisions. +- Emit deterministic exports (JSON, Trivy DB) for downstream policy evaluation. +- Coordinate offline/air-gap updates via Offline Kit bundles. + +## Key components +- `StellaOps.Concelier.WebService` orchestration host. +- Connector libraries under `StellaOps.Concelier.Connector.*`. +- Exporter packages (`StellaOps.Concelier.Exporter.*`). + +## Integrations & dependencies +- MongoDB for canonical observations and schedules. +- Policy Engine / Export Center / CLI for evidence consumption. +- Notify and UI for advisory deltas. + +## Operational notes +- Connector runbooks in ./operations/connectors/. +- Mirror operations for Offline Kit parity. +- Grafana dashboards for connector health. + +## Related resources +- ./operations/conflict-resolution.md +- ./operations/mirror.md + +## Backlog references +- DOCS-LNM-22-001, DOCS-LNM-22-007 in ../../TASKS.md. +- Connector-specific TODOs in `src/Concelier/**/TASKS.md`. + +## Epic alignment +- **Epic 1 – AOC enforcement:** uphold raw observation invariants, provenance requirements, linkset-only enrichment, and AOC verifier guardrails across every connector. +- **Epic 10 – Export Center:** expose deterministic advisory exports and metadata required by JSON/Trivy/mirror bundles. diff --git a/docs/modules/concelier/TASKS.md b/docs/modules/concelier/TASKS.md new file mode 100644 index 00000000..9326eadd --- /dev/null +++ b/docs/modules/concelier/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Concelier + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| CONCELIER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| CONCELIER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| CONCELIER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_CONCELIER.md b/docs/modules/concelier/architecture.md similarity index 82% rename from docs/ARCHITECTURE_CONCELIER.md rename to docs/modules/concelier/architecture.md index 16a6f9b4..c45e7798 100644 --- a/docs/ARCHITECTURE_CONCELIER.md +++ b/docs/modules/concelier/architecture.md @@ -1,518 +1,600 @@ -# component_architecture_concelier.md — **Stella Ops Concelier** (Sprint 22) - -> **Scope.** Implementation-ready architecture for **Concelier**: the advisory ingestion and Link-Not-Merge (LNM) observation pipeline that produces deterministic raw observations, correlation linksets, and evidence events consumed by Policy Engine, Console, CLI, and Export centers. Covers domain models, connectors, observation/linkset builders, storage schema, events, APIs, performance, security, and test matrices. - ---- - -## 0) Mission & boundaries - -**Mission.** Acquire authoritative **vulnerability advisories** (vendor PSIRTs, distros, OSS ecosystems, CERTs), persist them as immutable **observations** under the Aggregation-Only Contract (AOC), construct **linksets** that correlate observations without merging or precedence, and export deterministic evidence bundles (JSON, Trivy DB, Offline Kit) for downstream policy evaluation and operator tooling. - -**Boundaries.** - -* Concelier **does not** sign with private keys. When attestation is required, the export artifact is handed to the **Signer**/**Attestor** pipeline (out‑of‑process). -* Concelier **does not** decide PASS/FAIL; it provides data to the **Policy** engine. -* Online operation is **allowlist‑only**; air‑gapped deployments use the **Offline Kit**. - ---- - -## 1) Topology & processes - -**Process shape:** single ASP.NET Core service `StellaOps.Concelier.WebService` hosting: - -* **Scheduler** with distributed locks (Mongo backed). -* **Connectors** (fetch/parse/map) that emit immutable observation candidates. -* **Observation writer** enforcing AOC invariants via `AOCWriteGuard`. -* **Linkset builder** that correlates observations into `advisory_linksets` and annotates conflicts. -* **Event publisher** emitting `advisory.observation.updated` and `advisory.linkset.updated` messages. -* **Exporters** (JSON, Trivy DB, Offline Kit slices) fed from observation/linkset stores. -* **Minimal REST** for health/status/trigger/export and observation/linkset reads. - -**Scale:** HA by running N replicas; **locks** prevent overlapping jobs per source/exporter. - ---- - -## 2) Canonical domain model - -> Stored in MongoDB (database `concelier`), serialized with a **canonical JSON** writer (stable order, camelCase, normalized timestamps). - -### 2.1 Core entities - -#### AdvisoryObservation - -```jsonc -observationId // deterministic id: {tenant}:{source.vendor}:{upstreamId}:{revision} -tenant // issuing tenant (lower-case) -source{ - vendor, stream, api, collectorVersion -} -upstream{ - upstreamId, documentVersion, fetchedAt, receivedAt, - contentHash, signature{present, format?, keyId?, signature?} -} -content{ - format, specVersion, raw, metadata? -} -identifiers{ - cve?, ghsa?, vendorIds[], aliases[] -} -linkset{ - purls[], cpes[], aliases[], references[{type,url}], - reconciledFrom[] -} -createdAt // when Concelier recorded the observation -attributes // optional provenance metadata (batch ids, ingest cursor) -```jsonc - -#### AdvisoryLinkset - -```jsonc -linksetId // sha256 over sorted (tenant, product/vuln tuple, observation ids) -tenant -key{ - vulnerabilityId, - productKey, - confidence // low|medium|high -} -observations[] = [ - { - observationId, - sourceVendor, - statement{ - status?, severity?, references?, notes? - }, - collectedAt - } -] -aliases{ - primary, - others[] -} -purls[] -cpes[] -conflicts[]? // see AdvisoryLinksetConflict -createdAt -updatedAt -```jsonc - -#### AdvisoryLinksetConflict - -```jsonc -conflictId // deterministic hash -type // severity-mismatch | affected-range-divergence | reference-clash | alias-inconsistency | metadata-gap -field? // optional JSON pointer (e.g., /statement/severity/vector) -observations[] // per-source values contributing to the conflict -confidence // low|medium|high (heuristic weight) -detectedAt -```jsonc - -#### ObservationEvent / LinksetEvent - -```jsonc -eventId // ULID -tenant -type // advisory.observation.updated | advisory.linkset.updated -key{ - observationId? // on observation event - linksetId? // on linkset event - vulnerabilityId?, - productKey? -} -delta{ - added[], removed[], changed[] // normalized summary for consumers -} -hash // canonical hash of serialized delta payload -occurredAt -```jsonc - -#### ExportState - -```jsonc -exportKind // json | trivydb -baseExportId? // last full baseline -baseDigest? // digest of last full baseline -lastFullDigest? // digest of last full export -lastDeltaDigest? // digest of last delta export -cursor // per-kind incremental cursor -files[] // last manifest snapshot (path → sha256) -```jsonc - -Legacy `Advisory`, `Affected`, and merge-centric entities remain in the repository for historical exports and replay but are being phased out as Link-Not-Merge takes over. New code paths must interact with `AdvisoryObservation` / `AdvisoryLinkset` exclusively and emit conflicts through the structured payloads described above. - -### 2.2 Product identity (`productKey`) - -* **Primary:** `purl` (Package URL). -* **OS packages:** RPM (NEVRA→purl:rpm), DEB (dpkg→purl:deb), APK (apk→purl:alpine), with **EVR/NVRA** preserved. -* **Secondary:** `cpe` retained for compatibility; advisory records may carry both. -* **Image/platform:** `oci:/@` for image‑level advisories (rare). -* **Unmappable:** if a source is non‑deterministic, keep native string under `productKey="native::"` and mark **non‑joinable**. - ---- - -## 3) Source families & precedence - -### 3.1 Families - -* **Vendor PSIRTs**: Microsoft, Oracle, Cisco, Adobe, Apple, VMware, Chromium… -* **Linux distros**: Red Hat, SUSE, Ubuntu, Debian, Alpine… -* **OSS ecosystems**: OSV, GHSA (GitHub Security Advisories), PyPI, npm, Maven, NuGet, Go. -* **CERTs / national CSIRTs**: CISA (KEV, ICS), JVN, ACSC, CCCS, KISA, CERT‑FR/BUND, etc. - -### 3.2 Precedence (when claims conflict) - -1. **Vendor PSIRT** (authoritative for their product). -2. **Distro** (authoritative for packages they ship, including backports). -3. **Ecosystem** (OSV/GHSA) for library semantics. -4. **CERTs/aggregators** for enrichment (KEV/known exploited). - -> Precedence affects **Affected** ranges and **fixed** info; **severity** is normalized to the **maximum** credible severity unless policy overrides. Conflicts are retained with **source provenance**. - ---- - -## 4) Connectors & normalization - -### 4.1 Connector contract - -```csharp -public interface IFeedConnector { - string SourceName { get; } - Task FetchAsync(IServiceProvider sp, CancellationToken ct); // -> document collection - Task ParseAsync(IServiceProvider sp, CancellationToken ct); // -> dto collection (validated) - Task MapAsync(IServiceProvider sp, CancellationToken ct); // -> advisory/alias/affected/reference -} -```jsonc - -* **Fetch**: windowed (cursor), conditional GET (ETag/Last‑Modified), retry/backoff, rate limiting. -* **Parse**: schema validation (JSON Schema, XSD/CSAF), content type checks; write **DTO** with normalized casing. -* **Map**: build canonical records; all outputs carry **provenance** (doc digest, URI, anchors). - -### 4.2 Version range normalization - -* **SemVer** ecosystems (npm, pypi, maven, nuget, golang): normalize to `introduced`/`fixed` semver ranges (use `~`, `^`, `<`, `>=` canonicalized to intervals). -* **RPM EVR**: `epoch:version-release` with `rpmvercmp` semantics; store raw EVR strings and also **computed order keys** for query. -* **DEB**: dpkg version comparison semantics mirrored; store computed keys. -* **APK**: Alpine version semantics; compute order keys. -* **Generic**: if provider uses text, retain raw; do **not** invent ranges. - -### 4.3 Severity & CVSS - -* Normalize **CVSS v2/v3/v4** where available (vector, baseScore, severity). -* If multiple CVSS sources exist, track them all; **effective severity** defaults to **max** by policy (configurable). -* **ExploitKnown** toggled by KEV and equivalent sources; store **evidence** (source, date). - ---- - -## 5) Observation & linkset pipeline - -> **Goal:** deterministically ingest raw documents into immutable observations, correlate them into evidence-rich linksets, and broadcast changes without precedence or mutation. - -### 5.1 Observation flow - -1. **Connector fetch/parse/map** — connectors download upstream payloads, validate signatures, and map to DTOs (identifiers, references, raw payload, provenance). -2. **AOC guard** — `AOCWriteGuard` verifies forbidden keys, provenance completeness, tenant claims, timestamp normalization, and content hash idempotency. Violations raise `ERR_AOC_00x` mapped to structured logs and metrics. -3. **Append-only write** — observations insert into `advisory_observations`; duplicates by `(tenant, source.vendor, upstream.upstreamId, upstream.contentHash)` become no-ops; new content for same upstream id creates a supersedes chain. -4. **Change feed + event** — Mongo change streams trigger `advisory.observation.updated@1` events with deterministic payloads (IDs, hash, supersedes pointer, linkset summary). Policy Engine, Offline Kit builder, and guard dashboards subscribe. - -### 5.2 Linkset correlation - -1. **Queue** — observation deltas enqueue correlation jobs keyed by `(tenant, vulnerabilityId, productKey)` candidates derived from identifiers + alias graph. -2. **Canonical grouping** — builder resolves aliases using Concelier’s alias store and deterministic heuristics (vendor > distro > cert), deriving normalized product keys (purl preferred) and confidence scores. -3. **Linkset materialization** — `advisory_linksets` documents store sorted observation references, alias sets, product keys, range metadata, and conflict payloads. Writes are idempotent; unchanged hashes skip updates. -4. **Conflict detection** — builder emits structured conflicts (`severity-mismatch`, `affected-range-divergence`, `reference-clash`, `alias-inconsistency`, `metadata-gap`). Conflicts carry per-observation values for explainability. -5. **Event emission** — `advisory.linkset.updated@1` summarizes deltas (`added`, `removed`, `changed` observation IDs, conflict updates, confidence changes) and includes a canonical hash for replay validation. - -### 5.3 Event contract - -| Event | Schema | Notes | -|-------|--------|-------| -| `advisory.observation.updated@1` | `events/advisory.observation.updated@1.json` | Fired on new or superseded observations. Includes `observationId`, source metadata, `linksetSummary` (aliases/purls), supersedes pointer (if any), SHA-256 hash, and `traceId`. | -| `advisory.linkset.updated@1` | `events/advisory.linkset.updated@1.json` | Fired when correlation changes. Includes `linksetId`, `key{vulnerabilityId, productKey, confidence}`, observation deltas, conflicts, `updatedAt`, and canonical hash. | - -Events are emitted via NATS (primary) and Redis Stream (fallback). Consumers acknowledge idempotently using the hash; duplicates are safe. Offline Kit captures both topics during bundle creation for air-gapped replay. - ---- - -## 6) Storage schema (MongoDB) - -### Collections & indexes (LNM path) - -* `concelier.sources` `{_id, type, baseUrl, enabled, notes}` — connector catalog. -* `concelier.source_state` `{sourceName(unique), enabled, cursor, lastSuccess, backoffUntil, paceOverrides}` — run-state (TTL indexes on `backoffUntil`). -* `concelier.documents` `{_id, sourceName, uri, fetchedAt, sha256, contentType, status, metadata, gridFsId?, etag?, lastModified?}` — raw payload registry. - * Indexes: `{sourceName:1, uri:1}` unique; `{fetchedAt:-1}` for recent fetches. -* `concelier.dto` `{_id, sourceName, documentId, schemaVer, payload, validatedAt}` — normalized connector DTOs used for replay. - * Index: `{sourceName:1, documentId:1}`. -* `concelier.advisory_observations` - -``` -{ - _id: "tenant:vendor:upstreamId:revision", - tenant, - source: { vendor, stream, api, collectorVersion }, - upstream: { upstreamId, documentVersion, fetchedAt, receivedAt, contentHash, signature }, - content: { format, specVersion, raw, metadata? }, - identifiers: { cve?, ghsa?, vendorIds[], aliases[] }, - linkset: { purls[], cpes[], aliases[], references[], reconciledFrom[] }, - supersedes?: "prevObservationId", - createdAt, - attributes?: object -} -``` - - * Indexes: `{tenant:1, upstream.upstreamId:1}`, `{tenant:1, source.vendor:1, linkset.purls:1}`, `{tenant:1, linkset.aliases:1}`, `{tenant:1, createdAt:-1}`. -* `concelier.advisory_linksets` - -``` -{ - _id: "sha256:...", - tenant, - key: { vulnerabilityId, productKey, confidence }, - observations: [ - { observationId, sourceVendor, statement, collectedAt } - ], - aliases: { primary, others: [] }, - purls: [], - cpes: [], - conflicts: [], - createdAt, - updatedAt -} -``` - - * Indexes: `{tenant:1, key.vulnerabilityId:1, key.productKey:1}`, `{tenant:1, purls:1}`, `{tenant:1, aliases.primary:1}`, `{tenant:1, updatedAt:-1}`. -* `concelier.advisory_events` - -``` -{ - _id: ObjectId, - tenant, - type: "advisory.observation.updated" | "advisory.linkset.updated", - key, - delta, - hash, - occurredAt -} -``` - - * TTL index on `occurredAt` (configurable retention), `{type:1, occurredAt:-1}` for replay. -* `concelier.export_state` `{_id(exportKind), baseExportId?, baseDigest?, lastFullDigest?, lastDeltaDigest?, cursor, files[]}` -* `locks` `{_id(jobKey), holder, acquiredAt, heartbeatAt, leaseMs, ttlAt}` (TTL cleans dead locks) -* `jobs` `{_id, type, args, state, startedAt, heartbeatAt, endedAt, error}` - -**Legacy collections** (`advisory`, `alias`, `affected`, `reference`, `merge_event`) remain read-only during the migration window to support back-compat exports. New code must not write to them; scheduled cleanup removes them after Link-Not-Merge GA. - -**GridFS buckets**: `fs.documents` for raw payloads (immutable); `fs.exports` for historical JSON/Trivy archives. - ---- - -## 7) Exporters - -### 7.1 Deterministic JSON (vuln‑list style) - -* Folder structure mirroring `////…` with one JSON per advisory; deterministic ordering, stable timestamps, normalized whitespace. -* `manifest.json` lists all files with SHA‑256 and a top‑level **export digest**. - -### 7.2 Trivy DB exporter - -* Builds Bolt DB archives compatible with Trivy; supports **full** and **delta** modes. -* In delta, unchanged blobs are reused from the base; metadata captures: - - ```json - { - "mode": "delta|full", - "baseExportId": "...", - "baseManifestDigest": "sha256:...", - "changed": ["path1", "path2"], - "removed": ["path3"] - } - ``` -* Optional ORAS push (OCI layout) for registries. -* Offline kit bundles include Trivy DB + JSON tree + export manifest. -* Mirror-ready bundles: when `concelier.trivy.mirror` defines domains, the exporter emits `mirror/index.json` plus per-domain `manifest.json`, `metadata.json`, and `db.tar.gz` files with SHA-256 digests so Concelier mirrors can expose domain-scoped download endpoints. -* Concelier.WebService serves `/concelier/exports/index.json` and `/concelier/exports/mirror/{domain}/…` directly from the export tree with hour-long budgets (index: 60 s, bundles: 300 s, immutable) and per-domain rate limiting; the endpoints honour Stella Ops Authority or CIDR bypass lists depending on mirror topology. - -### 7.3 Hand‑off to Signer/Attestor (optional) - -* On export completion, if `attest: true` is set in job args, Concelier **posts** the artifact metadata to **Signer**/**Attestor**; Concelier itself **does not** hold signing keys. -* Export record stores returned `{ uuid, index, url }` from **Rekor v2**. - ---- - -## 8) REST APIs - -All under `/api/v1/concelier`. - -**Health & status** - -``` -GET /healthz | /readyz -GET /status → sources, last runs, export cursors -``` - -**Sources & jobs** - -``` -GET /sources → list of configured sources -POST /sources/{name}/trigger → { jobId } -POST /sources/{name}/pause | /resume → toggle -GET /jobs/{id} → job status -``` - -**Exports** - -``` -POST /exports/json { full?:bool, force?:bool, attest?:bool } → { exportId, digest, rekor? } -POST /exports/trivy { full?:bool, force?:bool, publish?:bool, attest?:bool } → { exportId, digest, rekor? } -GET /exports/{id} → export metadata (kind, digest, createdAt, rekor?) -GET /concelier/exports/index.json → mirror index describing available domains/bundles -GET /concelier/exports/mirror/{domain}/manifest.json -GET /concelier/exports/mirror/{domain}/bundle.json -GET /concelier/exports/mirror/{domain}/bundle.json.jws -``` - -**Search (operator debugging)** - -``` -GET /advisories/{key} -GET /advisories?scheme=CVE&value=CVE-2025-12345 -GET /affected?productKey=pkg:rpm/openssl&limit=100 -``` - -**AuthN/Z:** Authority tokens (OpTok) with roles: `concelier.read`, `concelier.admin`, `concelier.export`. - ---- - -## 9) Configuration (YAML) - -```yaml -concelier: - mongo: { uri: "mongodb://mongo/concelier" } - s3: - endpoint: "http://minio:9000" - bucket: "stellaops-concelier" - scheduler: - windowSeconds: 30 - maxParallelSources: 4 - sources: - - name: redhat - kind: csaf - baseUrl: https://access.redhat.com/security/data/csaf/v2/ - signature: { type: pgp, keys: [ "…redhat PGP…" ] } - enabled: true - windowDays: 7 - - name: suse - kind: csaf - baseUrl: https://ftp.suse.com/pub/projects/security/csaf/ - signature: { type: pgp, keys: [ "…suse PGP…" ] } - - name: ubuntu - kind: usn-json - baseUrl: https://ubuntu.com/security/notices.json - signature: { type: none } - - name: osv - kind: osv - baseUrl: https://api.osv.dev/v1/ - signature: { type: none } - - name: ghsa - kind: ghsa - baseUrl: https://api.github.com/graphql - auth: { tokenRef: "env:GITHUB_TOKEN" } - exporters: - json: - enabled: true - output: s3://stellaops-concelier/json/ - trivy: - enabled: true - mode: full - output: s3://stellaops-concelier/trivy/ - oras: - enabled: false - repo: ghcr.io/org/concelier - precedence: - vendorWinsOverDistro: true - distroWinsOverOsv: true - severity: - policy: max # or 'vendorPreferred' / 'distroPreferred' -``` - ---- - -## 10) Security & compliance - -* **Outbound allowlist** per connector (domains, protocols); proxy support; TLS pinning where possible. -* **Signature verification** for raw docs (PGP/cosign/x509) with results stored in `document.metadata.sig`. Docs failing verification may still be ingested but flagged; Policy Engine or downstream policy can down-weight them. -* **No secrets in logs**; auth material via `env:` or mounted files; HTTP redaction of `Authorization` headers. -* **Multi‑tenant**: per‑tenant DBs or prefixes; per‑tenant S3 prefixes; tenant‑scoped API tokens. -* **Determinism**: canonical JSON writer; export digests stable across runs given same inputs. - ---- - -## 11) Performance targets & scale - -* **Ingest**: ≥ 5k documents/min on 4 cores (CSAF/OpenVEX/JSON). -* **Normalize/map**: ≥ 50k observation statements/min on 4 cores. -* **Observation write**: ≤ 5 ms P95 per document (including guard + Mongo write). -* **Linkset build**: ≤ 15 ms P95 per `(vulnerabilityId, productKey)` update, even with 20+ contributing observations. -* **Export**: 1M advisories JSON in ≤ 90 s (streamed, zstd), Trivy DB in ≤ 60 s on 8 cores. -* **Memory**: hard cap per job; chunked streaming writers; backpressure to avoid GC spikes. - -**Scale pattern**: add Concelier replicas; Mongo scaling via indices and read/write concerns; GridFS only for oversized docs. - ---- - -## 12) Observability - -* **Metrics** - - * `concelier.fetch.docs_total{source}` - * `concelier.fetch.bytes_total{source}` - * `concelier.parse.failures_total{source}` - * `concelier.map.statements_total{source}` - * `concelier.observations.write_total{result=ok|noop|error}` - * `concelier.linksets.updated_total{result=ok|skip|error}` - * `concelier.linksets.conflicts_total{type}` - * `concelier.export.bytes{kind}` - * `concelier.export.duration_seconds{kind}` -* **Tracing** around fetch/parse/map/observe/linkset/export. -* **Logs**: structured with `source`, `uri`, `docDigest`, `advisoryKey`, `exportId`. - ---- - -## 13) Testing matrix - -* **Connectors:** fixture suites for each provider/format (happy path; malformed; signature fail). -* **Version semantics:** EVR vs dpkg vs semver edge cases (epoch bumps, tilde versions, pre‑releases). -* **Linkset correlation:** multi-source conflicts (severity, range, alias) produce deterministic conflict payloads; ensure confidence scoring stable. -* **Export determinism:** byte‑for‑byte stable outputs across runs; digest equality. -* **Performance:** soak tests with 1M advisories; cap memory; verify backpressure. -* **API:** pagination, filters, RBAC, error envelopes (RFC 7807). -* **Offline kit:** bundle build & import correctness. - ---- - -## 14) Failure modes & recovery - -* **Source outages:** scheduler backs off with exponential delay; `source_state.backoffUntil`; alerts on staleness. -* **Schema drifts:** parse stage marks DTO invalid; job fails with clear diagnostics; connector version flags track supported schema ranges. -* **Partial exports:** exporters write to temp prefix; **manifest commit** is atomic; only then move to final prefix and update `export_state`. -* **Resume:** all stages idempotent; `source_state.cursor` supports window resume. - ---- - -## 15) Operator runbook (quick) - -* **Trigger all sources:** `POST /api/v1/concelier/sources/*/trigger` -* **Force full export JSON:** `POST /api/v1/concelier/exports/json { "full": true, "force": true }` -* **Force Trivy DB delta publish:** `POST /api/v1/concelier/exports/trivy { "full": false, "publish": true }` -* **Inspect observation:** `GET /api/v1/concelier/observations/{observationId}` -* **Query linkset:** `GET /api/v1/concelier/linksets?vulnerabilityId=CVE-2025-12345&productKey=pkg:rpm/redhat/openssl` -* **Pause noisy source:** `POST /api/v1/concelier/sources/osv/pause` - ---- - -## 16) Rollout plan - -1. **MVP**: Red Hat (CSAF), SUSE (CSAF), Ubuntu (USN JSON), OSV; JSON export. -2. **Add**: GHSA GraphQL, Debian (DSA HTML/JSON), Alpine secdb; Trivy DB export. -3. **Attestation hand‑off**: integrate with **Signer/Attestor** (optional). -4. **Scale & diagnostics**: provider dashboards, staleness alerts, export cache reuse. -5. **Offline kit**: end‑to‑end verified bundles for air‑gap. +# component_architecture_concelier.md — **Stella Ops Concelier** (Sprint 22) + +> Derived from Epic 1 – AOC enforcement and aligned with the Export Center evidence interfaces first scoped in Epic 10. + +> **Scope.** Implementation-ready architecture for **Concelier**: the advisory ingestion and Link-Not-Merge (LNM) observation pipeline that produces deterministic raw observations, correlation linksets, and evidence events consumed by Policy Engine, Console, CLI, and Export centers. Covers domain models, connectors, observation/linkset builders, storage schema, events, APIs, performance, security, and test matrices. + +--- + +## 0) Mission & boundaries + +**Mission.** Acquire authoritative **vulnerability advisories** (vendor PSIRTs, distros, OSS ecosystems, CERTs), persist them as immutable **observations** under the Aggregation-Only Contract (AOC), construct **linksets** that correlate observations without merging or precedence, and export deterministic evidence bundles (JSON, Trivy DB, Offline Kit) for downstream policy evaluation and operator tooling. + +**Boundaries.** + +* Concelier **does not** sign with private keys. When attestation is required, the export artifact is handed to the **Signer**/**Attestor** pipeline (out‑of‑process). +* Concelier **does not** decide PASS/FAIL; it provides data to the **Policy** engine. +* Online operation is **allowlist‑only**; air‑gapped deployments use the **Offline Kit**. + +--- + +## 1) Aggregation-Only Contract guardrails + +**Epic 1 distilled** — the service itself is the enforcement point for AOC. The guardrail checklist is embedded in code (`AOCWriteGuard`) and must be satisfied before any advisory hits Mongo: + +1. **No derived semantics in ingestion.** The DTOs produced by connectors cannot contain severity, consensus, reachability, merged status, or fix hints. Roslyn analyzers (`StellaOps.AOC.Analyzers`) scan connectors and fail builds if forbidden properties appear. +2. **Immutable raw docs.** Every upstream advisory is persisted in `advisory_raw` with append-only semantics. Revisions produce new `_id`s via version suffix (`:v2`, `:v3`), linking back through `supersedes`. +3. **Mandatory provenance.** Collectors record `source`, `upstream` metadata (`document_version`, `fetched_at`, `received_at`, `content_hash`), and signature presence before writing. +4. **Linkset only.** Derived joins (aliases, PURLs, CPEs, references) are stored inside `linkset` and never mutate `content.raw`. +5. **Deterministic canonicalisation.** Writers use canonical JSON (sorted object keys, lexicographic arrays) ensuring identical inputs yield the same hashes/diff-friendly outputs. +6. **Idempotent upserts.** `(source.vendor, upstream.upstream_id, upstream.content_hash)` uniquely identify a document. Duplicate hashes short-circuit; new hashes create a new version. +7. **Verifier & CI.** `StellaOps.AOC.Verifier` processes observation batches in CI and at runtime, rejecting writes lacking provenance, introducing unordered collections, or violating the schema. + +### 1.1 Advisory raw document shape + +```json +{ + "_id": "advisory_raw:osv:GHSA-xxxx-....:v3", + "source": { + "vendor": "OSV", + "stream": "github", + "api": "https://api.osv.dev/v1/.../GHSA-...", + "collector_version": "concelier/1.7.3" + }, + "upstream": { + "upstream_id": "GHSA-xxxx-....", + "document_version": "2025-09-01T12:13:14Z", + "fetched_at": "2025-09-01T13:04:05Z", + "received_at": "2025-09-01T13:04:06Z", + "content_hash": "sha256:...", + "signature": { + "present": true, + "format": "dsse", + "key_id": "rekor:.../key/abc", + "sig": "base64..." + } + }, + "content": { + "format": "OSV", + "spec_version": "1.6", + "raw": { /* unmodified upstream document */ } + }, + "identifiers": { + "cve": ["CVE-2025-12345"], + "ghsa": ["GHSA-xxxx-...."], + "aliases": ["CVE-2025-12345", "GHSA-xxxx-...."] + }, + "linkset": { + "purls": ["pkg:npm/lodash@4.17.21"], + "cpes": ["cpe:2.3:a:lodash:lodash:4.17.21:*:*:*:*:*:*:*"], + "references": [ + {"type":"advisory","url":"https://..."}, + {"type":"fix","url":"https://..."} + ], + "reconciled_from": ["content.raw.affected.ranges", "content.raw.pkg"] + }, + "supersedes": "advisory_raw:osv:GHSA-xxxx-....:v2", + "tenant": "default" +} +``` + +### 1.2 Connector lifecycle + +1. **Snapshot stage** — connectors fetch signed feeds or use offline mirrors keyed by `{vendor, stream, snapshot_date}`. +2. **Parse stage** — upstream payloads are normalised into strongly-typed DTOs with UTC timestamps. +3. **Guard stage** — DTOs run through `AOCWriteGuard` performing schema validation, forbidden-field checks, provenance validation, deterministic sorting, and `_id` computation. +4. **Write stage** — append-only Mongo insert; duplicate hash is ignored, changed hash creates a new version and emits `supersedes` pointer. +5. **Event stage** — DSSE-backed events `advisory.observation.updated` and `advisory.linkset.updated` notify downstream services (Policy, Export Center, CLI). + +### 1.3 Export readiness + +Concelier feeds Export Center profiles (Epic 10) by: + +- Maintaining canonical JSON exports with deterministic manifests (`export.json`) listing content hashes, counts, and `supersedes` chains. +- Producing Trivy DB-compatible artifacts (SQLite + metadata) packaged under `db/` with hash manifests. +- Surfacing mirror manifests that reference Mongo snapshot digests, enabling Offline Kit bundle verification. + +Running the same export job twice against the same snapshot must yield byte-identical archives and manifest hashes. + +--- + +## 2) Topology & processes + +**Process shape:** single ASP.NET Core service `StellaOps.Concelier.WebService` hosting: + +* **Scheduler** with distributed locks (Mongo backed). +* **Connectors** (fetch/parse/map) that emit immutable observation candidates. +* **Observation writer** enforcing AOC invariants via `AOCWriteGuard`. +* **Linkset builder** that correlates observations into `advisory_linksets` and annotates conflicts. +* **Event publisher** emitting `advisory.observation.updated` and `advisory.linkset.updated` messages. +* **Exporters** (JSON, Trivy DB, Offline Kit slices) fed from observation/linkset stores. +* **Minimal REST** for health/status/trigger/export and observation/linkset reads. + +**Scale:** HA by running N replicas; **locks** prevent overlapping jobs per source/exporter. + +--- + +## 3) Canonical domain model + +> Stored in MongoDB (database `concelier`), serialized with a **canonical JSON** writer (stable order, camelCase, normalized timestamps). + +### 2.1 Core entities + +#### AdvisoryObservation + +```jsonc +observationId // deterministic id: {tenant}:{source.vendor}:{upstreamId}:{revision} +tenant // issuing tenant (lower-case) +source{ + vendor, stream, api, collectorVersion +} +upstream{ + upstreamId, documentVersion, fetchedAt, receivedAt, + contentHash, signature{present, format?, keyId?, signature?} +} +content{ + format, specVersion, raw, metadata? +} +identifiers{ + cve?, ghsa?, vendorIds[], aliases[] +} +linkset{ + purls[], cpes[], aliases[], references[{type,url}], + reconciledFrom[] +} +createdAt // when Concelier recorded the observation +attributes // optional provenance metadata (batch ids, ingest cursor) +```jsonc + +#### AdvisoryLinkset + +```jsonc +linksetId // sha256 over sorted (tenant, product/vuln tuple, observation ids) +tenant +key{ + vulnerabilityId, + productKey, + confidence // low|medium|high +} +observations[] = [ + { + observationId, + sourceVendor, + statement{ + status?, severity?, references?, notes? + }, + collectedAt + } +] +aliases{ + primary, + others[] +} +purls[] +cpes[] +conflicts[]? // see AdvisoryLinksetConflict +createdAt +updatedAt +```jsonc + +#### AdvisoryLinksetConflict + +```jsonc +conflictId // deterministic hash +type // severity-mismatch | affected-range-divergence | reference-clash | alias-inconsistency | metadata-gap +field? // optional JSON pointer (e.g., /statement/severity/vector) +observations[] // per-source values contributing to the conflict +confidence // low|medium|high (heuristic weight) +detectedAt +```jsonc + +#### ObservationEvent / LinksetEvent + +```jsonc +eventId // ULID +tenant +type // advisory.observation.updated | advisory.linkset.updated +key{ + observationId? // on observation event + linksetId? // on linkset event + vulnerabilityId?, + productKey? +} +delta{ + added[], removed[], changed[] // normalized summary for consumers +} +hash // canonical hash of serialized delta payload +occurredAt +```jsonc + +#### ExportState + +```jsonc +exportKind // json | trivydb +baseExportId? // last full baseline +baseDigest? // digest of last full baseline +lastFullDigest? // digest of last full export +lastDeltaDigest? // digest of last delta export +cursor // per-kind incremental cursor +files[] // last manifest snapshot (path → sha256) +```jsonc + +Legacy `Advisory`, `Affected`, and merge-centric entities remain in the repository for historical exports and replay but are being phased out as Link-Not-Merge takes over. New code paths must interact with `AdvisoryObservation` / `AdvisoryLinkset` exclusively and emit conflicts through the structured payloads described above. + +### 2.2 Product identity (`productKey`) + +* **Primary:** `purl` (Package URL). +* **OS packages:** RPM (NEVRA→purl:rpm), DEB (dpkg→purl:deb), APK (apk→purl:alpine), with **EVR/NVRA** preserved. +* **Secondary:** `cpe` retained for compatibility; advisory records may carry both. +* **Image/platform:** `oci:/@` for image‑level advisories (rare). +* **Unmappable:** if a source is non‑deterministic, keep native string under `productKey="native::"` and mark **non‑joinable**. + +--- + +## 4) Source families & precedence + +### 3.1 Families + +* **Vendor PSIRTs**: Microsoft, Oracle, Cisco, Adobe, Apple, VMware, Chromium… +* **Linux distros**: Red Hat, SUSE, Ubuntu, Debian, Alpine… +* **OSS ecosystems**: OSV, GHSA (GitHub Security Advisories), PyPI, npm, Maven, NuGet, Go. +* **CERTs / national CSIRTs**: CISA (KEV, ICS), JVN, ACSC, CCCS, KISA, CERT‑FR/BUND, etc. + +### 3.2 Precedence (when claims conflict) + +1. **Vendor PSIRT** (authoritative for their product). +2. **Distro** (authoritative for packages they ship, including backports). +3. **Ecosystem** (OSV/GHSA) for library semantics. +4. **CERTs/aggregators** for enrichment (KEV/known exploited). + +> Precedence affects **Affected** ranges and **fixed** info; **severity** is normalized to the **maximum** credible severity unless policy overrides. Conflicts are retained with **source provenance**. + +--- + +## 5) Connectors & normalization + +### 4.1 Connector contract + +```csharp +public interface IFeedConnector { + string SourceName { get; } + Task FetchAsync(IServiceProvider sp, CancellationToken ct); // -> document collection + Task ParseAsync(IServiceProvider sp, CancellationToken ct); // -> dto collection (validated) + Task MapAsync(IServiceProvider sp, CancellationToken ct); // -> advisory/alias/affected/reference +} +```jsonc + +* **Fetch**: windowed (cursor), conditional GET (ETag/Last‑Modified), retry/backoff, rate limiting. +* **Parse**: schema validation (JSON Schema, XSD/CSAF), content type checks; write **DTO** with normalized casing. +* **Map**: build canonical records; all outputs carry **provenance** (doc digest, URI, anchors). + +### 4.2 Version range normalization + +* **SemVer** ecosystems (npm, pypi, maven, nuget, golang): normalize to `introduced`/`fixed` semver ranges (use `~`, `^`, `<`, `>=` canonicalized to intervals). +* **RPM EVR**: `epoch:version-release` with `rpmvercmp` semantics; store raw EVR strings and also **computed order keys** for query. +* **DEB**: dpkg version comparison semantics mirrored; store computed keys. +* **APK**: Alpine version semantics; compute order keys. +* **Generic**: if provider uses text, retain raw; do **not** invent ranges. + +### 4.3 Severity & CVSS + +* Normalize **CVSS v2/v3/v4** where available (vector, baseScore, severity). +* If multiple CVSS sources exist, track them all; **effective severity** defaults to **max** by policy (configurable). +* **ExploitKnown** toggled by KEV and equivalent sources; store **evidence** (source, date). + +--- + +## 6) Observation & linkset pipeline + +> **Goal:** deterministically ingest raw documents into immutable observations, correlate them into evidence-rich linksets, and broadcast changes without precedence or mutation. + +### 5.1 Observation flow + +1. **Connector fetch/parse/map** — connectors download upstream payloads, validate signatures, and map to DTOs (identifiers, references, raw payload, provenance). +2. **AOC guard** — `AOCWriteGuard` verifies forbidden keys, provenance completeness, tenant claims, timestamp normalization, and content hash idempotency. Violations raise `ERR_AOC_00x` mapped to structured logs and metrics. +3. **Append-only write** — observations insert into `advisory_observations`; duplicates by `(tenant, source.vendor, upstream.upstreamId, upstream.contentHash)` become no-ops; new content for same upstream id creates a supersedes chain. +4. **Change feed + event** — Mongo change streams trigger `advisory.observation.updated@1` events with deterministic payloads (IDs, hash, supersedes pointer, linkset summary). Policy Engine, Offline Kit builder, and guard dashboards subscribe. + +### 5.2 Linkset correlation + +1. **Queue** — observation deltas enqueue correlation jobs keyed by `(tenant, vulnerabilityId, productKey)` candidates derived from identifiers + alias graph. +2. **Canonical grouping** — builder resolves aliases using Concelier’s alias store and deterministic heuristics (vendor > distro > cert), deriving normalized product keys (purl preferred) and confidence scores. +3. **Linkset materialization** — `advisory_linksets` documents store sorted observation references, alias sets, product keys, range metadata, and conflict payloads. Writes are idempotent; unchanged hashes skip updates. +4. **Conflict detection** — builder emits structured conflicts (`severity-mismatch`, `affected-range-divergence`, `reference-clash`, `alias-inconsistency`, `metadata-gap`). Conflicts carry per-observation values for explainability. +5. **Event emission** — `advisory.linkset.updated@1` summarizes deltas (`added`, `removed`, `changed` observation IDs, conflict updates, confidence changes) and includes a canonical hash for replay validation. + +### 5.3 Event contract + +| Event | Schema | Notes | +|-------|--------|-------| +| `advisory.observation.updated@1` | `events/advisory.observation.updated@1.json` | Fired on new or superseded observations. Includes `observationId`, source metadata, `linksetSummary` (aliases/purls), supersedes pointer (if any), SHA-256 hash, and `traceId`. | +| `advisory.linkset.updated@1` | `events/advisory.linkset.updated@1.json` | Fired when correlation changes. Includes `linksetId`, `key{vulnerabilityId, productKey, confidence}`, observation deltas, conflicts, `updatedAt`, and canonical hash. | + +Events are emitted via NATS (primary) and Redis Stream (fallback). Consumers acknowledge idempotently using the hash; duplicates are safe. Offline Kit captures both topics during bundle creation for air-gapped replay. + +--- + +## 7) Storage schema (MongoDB) + +### Collections & indexes (LNM path) + +* `concelier.sources` `{_id, type, baseUrl, enabled, notes}` — connector catalog. +* `concelier.source_state` `{sourceName(unique), enabled, cursor, lastSuccess, backoffUntil, paceOverrides}` — run-state (TTL indexes on `backoffUntil`). +* `concelier.documents` `{_id, sourceName, uri, fetchedAt, sha256, contentType, status, metadata, gridFsId?, etag?, lastModified?}` — raw payload registry. + * Indexes: `{sourceName:1, uri:1}` unique; `{fetchedAt:-1}` for recent fetches. +* `concelier.dto` `{_id, sourceName, documentId, schemaVer, payload, validatedAt}` — normalized connector DTOs used for replay. + * Index: `{sourceName:1, documentId:1}`. +* `concelier.advisory_observations` + +``` +{ + _id: "tenant:vendor:upstreamId:revision", + tenant, + source: { vendor, stream, api, collectorVersion }, + upstream: { upstreamId, documentVersion, fetchedAt, receivedAt, contentHash, signature }, + content: { format, specVersion, raw, metadata? }, + identifiers: { cve?, ghsa?, vendorIds[], aliases[] }, + linkset: { purls[], cpes[], aliases[], references[], reconciledFrom[] }, + supersedes?: "prevObservationId", + createdAt, + attributes?: object +} +``` + + * Indexes: `{tenant:1, upstream.upstreamId:1}`, `{tenant:1, source.vendor:1, linkset.purls:1}`, `{tenant:1, linkset.aliases:1}`, `{tenant:1, createdAt:-1}`. +* `concelier.advisory_linksets` + +``` +{ + _id: "sha256:...", + tenant, + key: { vulnerabilityId, productKey, confidence }, + observations: [ + { observationId, sourceVendor, statement, collectedAt } + ], + aliases: { primary, others: [] }, + purls: [], + cpes: [], + conflicts: [], + createdAt, + updatedAt +} +``` + + * Indexes: `{tenant:1, key.vulnerabilityId:1, key.productKey:1}`, `{tenant:1, purls:1}`, `{tenant:1, aliases.primary:1}`, `{tenant:1, updatedAt:-1}`. +* `concelier.advisory_events` + +``` +{ + _id: ObjectId, + tenant, + type: "advisory.observation.updated" | "advisory.linkset.updated", + key, + delta, + hash, + occurredAt +} +``` + + * TTL index on `occurredAt` (configurable retention), `{type:1, occurredAt:-1}` for replay. +* `concelier.export_state` `{_id(exportKind), baseExportId?, baseDigest?, lastFullDigest?, lastDeltaDigest?, cursor, files[]}` +* `locks` `{_id(jobKey), holder, acquiredAt, heartbeatAt, leaseMs, ttlAt}` (TTL cleans dead locks) +* `jobs` `{_id, type, args, state, startedAt, heartbeatAt, endedAt, error}` + +**Legacy collections** (`advisory`, `alias`, `affected`, `reference`, `merge_event`) remain read-only during the migration window to support back-compat exports. New code must not write to them; scheduled cleanup removes them after Link-Not-Merge GA. + +**GridFS buckets**: `fs.documents` for raw payloads (immutable); `fs.exports` for historical JSON/Trivy archives. + +--- + +## 8) Exporters + +### 7.1 Deterministic JSON (vuln‑list style) + +* Folder structure mirroring `////…` with one JSON per advisory; deterministic ordering, stable timestamps, normalized whitespace. +* `manifest.json` lists all files with SHA‑256 and a top‑level **export digest**. + +### 7.2 Trivy DB exporter + +* Builds Bolt DB archives compatible with Trivy; supports **full** and **delta** modes. +* In delta, unchanged blobs are reused from the base; metadata captures: + + ```json + { + "mode": "delta|full", + "baseExportId": "...", + "baseManifestDigest": "sha256:...", + "changed": ["path1", "path2"], + "removed": ["path3"] + } + ``` +* Optional ORAS push (OCI layout) for registries. +* Offline kit bundles include Trivy DB + JSON tree + export manifest. +* Mirror-ready bundles: when `concelier.trivy.mirror` defines domains, the exporter emits `mirror/index.json` plus per-domain `manifest.json`, `metadata.json`, and `db.tar.gz` files with SHA-256 digests so Concelier mirrors can expose domain-scoped download endpoints. +* Concelier.WebService serves `/concelier/exports/index.json` and `/concelier/exports/mirror/{domain}/…` directly from the export tree with hour-long budgets (index: 60 s, bundles: 300 s, immutable) and per-domain rate limiting; the endpoints honour Stella Ops Authority or CIDR bypass lists depending on mirror topology. + +### 7.3 Hand‑off to Signer/Attestor (optional) + +* On export completion, if `attest: true` is set in job args, Concelier **posts** the artifact metadata to **Signer**/**Attestor**; Concelier itself **does not** hold signing keys. +* Export record stores returned `{ uuid, index, url }` from **Rekor v2**. + +--- + +## 9) REST APIs + +All under `/api/v1/concelier`. + +**Health & status** + +``` +GET /healthz | /readyz +GET /status → sources, last runs, export cursors +``` + +**Sources & jobs** + +``` +GET /sources → list of configured sources +POST /sources/{name}/trigger → { jobId } +POST /sources/{name}/pause | /resume → toggle +GET /jobs/{id} → job status +``` + +**Exports** + +``` +POST /exports/json { full?:bool, force?:bool, attest?:bool } → { exportId, digest, rekor? } +POST /exports/trivy { full?:bool, force?:bool, publish?:bool, attest?:bool } → { exportId, digest, rekor? } +GET /exports/{id} → export metadata (kind, digest, createdAt, rekor?) +GET /concelier/exports/index.json → mirror index describing available domains/bundles +GET /concelier/exports/mirror/{domain}/manifest.json +GET /concelier/exports/mirror/{domain}/bundle.json +GET /concelier/exports/mirror/{domain}/bundle.json.jws +``` + +**Search (operator debugging)** + +``` +GET /advisories/{key} +GET /advisories?scheme=CVE&value=CVE-2025-12345 +GET /affected?productKey=pkg:rpm/openssl&limit=100 +``` + +**AuthN/Z:** Authority tokens (OpTok) with roles: `concelier.read`, `concelier.admin`, `concelier.export`. + +--- + +## 10) Configuration (YAML) + +```yaml +concelier: + mongo: { uri: "mongodb://mongo/concelier" } + s3: + endpoint: "http://minio:9000" + bucket: "stellaops-concelier" + scheduler: + windowSeconds: 30 + maxParallelSources: 4 + sources: + - name: redhat + kind: csaf + baseUrl: https://access.redhat.com/security/data/csaf/v2/ + signature: { type: pgp, keys: [ "…redhat PGP…" ] } + enabled: true + windowDays: 7 + - name: suse + kind: csaf + baseUrl: https://ftp.suse.com/pub/projects/security/csaf/ + signature: { type: pgp, keys: [ "…suse PGP…" ] } + - name: ubuntu + kind: usn-json + baseUrl: https://ubuntu.com/security/notices.json + signature: { type: none } + - name: osv + kind: osv + baseUrl: https://api.osv.dev/v1/ + signature: { type: none } + - name: ghsa + kind: ghsa + baseUrl: https://api.github.com/graphql + auth: { tokenRef: "env:GITHUB_TOKEN" } + exporters: + json: + enabled: true + output: s3://stellaops-concelier/json/ + trivy: + enabled: true + mode: full + output: s3://stellaops-concelier/trivy/ + oras: + enabled: false + repo: ghcr.io/org/concelier + precedence: + vendorWinsOverDistro: true + distroWinsOverOsv: true + severity: + policy: max # or 'vendorPreferred' / 'distroPreferred' +``` + +--- + +## 11) Security & compliance + +* **Outbound allowlist** per connector (domains, protocols); proxy support; TLS pinning where possible. +* **Signature verification** for raw docs (PGP/cosign/x509) with results stored in `document.metadata.sig`. Docs failing verification may still be ingested but flagged; Policy Engine or downstream policy can down-weight them. +* **No secrets in logs**; auth material via `env:` or mounted files; HTTP redaction of `Authorization` headers. +* **Multi‑tenant**: per‑tenant DBs or prefixes; per‑tenant S3 prefixes; tenant‑scoped API tokens. +* **Determinism**: canonical JSON writer; export digests stable across runs given same inputs. + +--- + +## 12) Performance targets & scale + +* **Ingest**: ≥ 5k documents/min on 4 cores (CSAF/OpenVEX/JSON). +* **Normalize/map**: ≥ 50k observation statements/min on 4 cores. +* **Observation write**: ≤ 5 ms P95 per document (including guard + Mongo write). +* **Linkset build**: ≤ 15 ms P95 per `(vulnerabilityId, productKey)` update, even with 20+ contributing observations. +* **Export**: 1M advisories JSON in ≤ 90 s (streamed, zstd), Trivy DB in ≤ 60 s on 8 cores. +* **Memory**: hard cap per job; chunked streaming writers; backpressure to avoid GC spikes. + +**Scale pattern**: add Concelier replicas; Mongo scaling via indices and read/write concerns; GridFS only for oversized docs. + +--- + +## 13) Observability + +* **Metrics** + + * `concelier.fetch.docs_total{source}` + * `concelier.fetch.bytes_total{source}` + * `concelier.parse.failures_total{source}` + * `concelier.map.statements_total{source}` + * `concelier.observations.write_total{result=ok|noop|error}` + * `concelier.linksets.updated_total{result=ok|skip|error}` + * `concelier.linksets.conflicts_total{type}` + * `concelier.export.bytes{kind}` + * `concelier.export.duration_seconds{kind}` +* **Tracing** around fetch/parse/map/observe/linkset/export. +* **Logs**: structured with `source`, `uri`, `docDigest`, `advisoryKey`, `exportId`. + +--- + +## 14) Testing matrix + +* **Connectors:** fixture suites for each provider/format (happy path; malformed; signature fail). +* **Version semantics:** EVR vs dpkg vs semver edge cases (epoch bumps, tilde versions, pre‑releases). +* **Linkset correlation:** multi-source conflicts (severity, range, alias) produce deterministic conflict payloads; ensure confidence scoring stable. +* **Export determinism:** byte‑for‑byte stable outputs across runs; digest equality. +* **Performance:** soak tests with 1M advisories; cap memory; verify backpressure. +* **API:** pagination, filters, RBAC, error envelopes (RFC 7807). +* **Offline kit:** bundle build & import correctness. + +--- + +## 15) Failure modes & recovery + +* **Source outages:** scheduler backs off with exponential delay; `source_state.backoffUntil`; alerts on staleness. +* **Schema drifts:** parse stage marks DTO invalid; job fails with clear diagnostics; connector version flags track supported schema ranges. +* **Partial exports:** exporters write to temp prefix; **manifest commit** is atomic; only then move to final prefix and update `export_state`. +* **Resume:** all stages idempotent; `source_state.cursor` supports window resume. + +--- + +## 16) Operator runbook (quick) + +* **Trigger all sources:** `POST /api/v1/concelier/sources/*/trigger` +* **Force full export JSON:** `POST /api/v1/concelier/exports/json { "full": true, "force": true }` +* **Force Trivy DB delta publish:** `POST /api/v1/concelier/exports/trivy { "full": false, "publish": true }` +* **Inspect observation:** `GET /api/v1/concelier/observations/{observationId}` +* **Query linkset:** `GET /api/v1/concelier/linksets?vulnerabilityId=CVE-2025-12345&productKey=pkg:rpm/redhat/openssl` +* **Pause noisy source:** `POST /api/v1/concelier/sources/osv/pause` + +--- + +## 17) Rollout plan + +1. **MVP**: Red Hat (CSAF), SUSE (CSAF), Ubuntu (USN JSON), OSV; JSON export. +2. **Add**: GHSA GraphQL, Debian (DSA HTML/JSON), Alpine secdb; Trivy DB export. +3. **Attestation hand‑off**: integrate with **Signer/Attestor** (optional). +4. **Scale & diagnostics**: provider dashboards, staleness alerts, export cache reuse. +5. **Offline kit**: end‑to‑end verified bundles for air‑gap. diff --git a/docs/modules/concelier/implementation_plan.md b/docs/modules/concelier/implementation_plan.md new file mode 100644 index 00000000..f1675173 --- /dev/null +++ b/docs/modules/concelier/implementation_plan.md @@ -0,0 +1,67 @@ +# Implementation plan — Concelier + +## Delivery timeline +- **Phase 1 — Guardrails & schema** + Stand up Mongo JSON validators for `advisory_raw` and `vex_raw`, wire the `AOCWriteGuard` repository interceptor, and seed deterministic linkset builders. Freeze legacy normalisation paths and migrate callers to the new raw schema. +- **Phase 2 — API & observability** + Publish ingestion and verification endpoints (`POST /ingest/*`, `GET /advisories.raw`, `POST /aoc/verify`) with Authority scopes, expose telemetry (`aoc_violation_total`, guard spans, structured logs), and ensure Offline Kit packaging captures validator deployment steps. +- **Phase 3 — Experience polish** + Ship CLI/Console affordances (`stella sources ingest --dry-run`, dashboard tiles, violation drill-downs), finish Export Center hand-off metadata, and close out CI enforcement (`stella aoc verify` preflight, AST lint, seeded fixtures). + +## Work breakdown by component +- **Concelier WebService & worker** + - Add Mongo validators and unique indexes over `(tenant, source.vendor, upstream.upstream_id, upstream.content_hash)`. + - Implement write interceptors rejecting forbidden fields, missing provenance, or merge attempts. + - Deterministically compute linksets and persist canonical JSON payloads. + - Introduce `/ingest/advisory`, `/advisories/raw*`, and `/aoc/verify` surfaces guarded by `advisory:*` and `aoc:verify` scopes. + - Emit guard metrics/traces and surface supersedes/violation audit logs. +- **Excititor (shared ingestion contract)** + - Mirror Concelier guard and schema changes for `vex_raw`. + - Maintain restart-time plug-in determinism and linkset extraction parity. +- **Shared libraries** + - Publish `StellaOps.Ingestion.AOC` (forbidden key catalog, guard middleware, provenance helpers, signature verification). + - Share error codes (`ERR_AOC_00x`) and deterministic hashing utilities. +- **Policy Engine integration** + - Enforce `effective_finding_*` write exclusivity. + - Consume only raw documents + linksets, removing any implicit normalisation. +- **Authority scopes** + - Provision `advisory:ingest|read`, `vex:ingest|read`, `aoc:verify`; propagate tenant claims to ingestion services. +- **CLI & Console** + - Implement `stella sources ingest --dry-run` and `stella aoc verify` (with exit codes mapped to `ERR_AOC_00x`). + - Surface AOC dashboards, violation drill-down, and verification shortcuts in the Console. +- **CI/CD** + - Add Roslyn analyzer / AST lint to block forbidden writes. + - Seed fixtures and run `stella aoc verify` against snapshots in pipeline gating. + +## Documentation deliverables +- Update `docs/ingestion/aggregation-only-contract.md` with guard invariants, schemas, error codes, and migration guidance. +- Refresh `docs/modules/concelier/operations/*.md` (mirror, conflict-resolution, authority audit) with validator rollouts and observability dashboards. +- Cross-link Authority scope definitions, CLI reference, Console sources guide, and observability runbooks to the AOC guard changes. +- Ensure Offline Kit documentation captures validator bootstrap and verify workflows. + +## Acceptance criteria +- Mongo validators and runtime guards reject forbidden fields and missing provenance with the documented `ERR_AOC_00x` codes. +- Linksets and supersedes chains are deterministic; rerunning ingestion over identical payloads yields byte-identical documents. +- CLI `stella aoc verify` exits non-zero on seeded violations and zero on clean datasets; Console dashboards show real-time guard status. +- Export Center consumes advisory datasets without relying on legacy normalised fields. +- CI fails if lint rules detect forbidden writes or if seeded guard tests regress. + +## Risks & mitigations +- **Collector drift introduces new forbidden keys.** Mitigated by guard middleware + CI lint + schema validation; RFC required for linkset changes. +- **Migration complexity from legacy normalisation.** Staged cutover with `_backup_*` copies and temporary views to keep Policy Engine parity. +- **Performance overhead during ingest.** Guard remains O(number of keys); index review ensures insert latency stays within warm (<5 s) / cold (<30 s) targets. +- **Tenancy leakage.** `tenant` required in schema, Authority-supplied claims enforced per request, observability alerts fire on missing tenant identifiers. + +## Test strategy +- **Unit**: guard rejection paths, provenance enforcement, idempotent insertions, linkset determinism. +- **Property**: fuzz upstream payloads to guarantee no forbidden fields emerge. +- **Integration**: batch ingest (50k advisories, mixed VEX fixtures), verifying zero guard violations and consistent supersedes. +- **Contract**: Policy Engine consumers verify raw-only reads; Export Center consumes canonical datasets. +- **End-to-end**: ingest/verify flow with CLI + Console actions to confirm observability and guard reporting. + +## Definition of done +- Validators deployed and verified in staging/offline environments. +- Runtime guards, CLI/Console workflows, and CI linting all active. +- Observability dashboards and runbooks updated; metrics visible. +- Documentation updates merged; Offline Kit instructions published. +- ./TASKS.md reflects status transitions; cross-module dependencies acknowledged in ../../TASKS.md. diff --git a/docs/ops/concelier-authority-audit-runbook.md b/docs/modules/concelier/operations/authority-audit-runbook.md similarity index 97% rename from docs/ops/concelier-authority-audit-runbook.md rename to docs/modules/concelier/operations/authority-audit-runbook.md index eb8a64c1..369c0657 100644 --- a/docs/ops/concelier-authority-audit-runbook.md +++ b/docs/modules/concelier/operations/authority-audit-runbook.md @@ -1,159 +1,159 @@ -# Concelier Authority Audit Runbook - -_Last updated: 2025-10-22_ - -This runbook helps operators verify and monitor the StellaOps Concelier ⇆ Authority integration. It focuses on the `/jobs*` surface, which now requires StellaOps Authority tokens, and the corresponding audit/metric signals that expose authentication and bypass activity. - -## 1. Prerequisites - -- Authority integration is enabled in `concelier.yaml` (or via `CONCELIER_AUTHORITY__*` environment variables) with a valid `clientId`, secret, audience, and required scopes. -- OTLP metrics/log exporters are configured (`concelier.telemetry.*`) or container stdout is shipped to your SIEM. -- Operators have access to the Concelier job trigger endpoints via CLI or REST for smoke tests. -- The rollout table in `docs/10_CONCELIER_CLI_QUICKSTART.md` has been reviewed so stakeholders align on the staged → enforced toggle timeline. - -### Configuration snippet - -```yaml -concelier: - authority: - enabled: true - allowAnonymousFallback: false # keep true only during initial rollout - issuer: "https://authority.internal" - audiences: - - "api://concelier" - requiredScopes: - - "concelier.jobs.trigger" - - "advisory:read" - - "advisory:ingest" - requiredTenants: - - "tenant-default" - bypassNetworks: - - "127.0.0.1/32" - - "::1/128" - clientId: "concelier-jobs" - clientSecretFile: "/run/secrets/concelier_authority_client" - tokenClockSkewSeconds: 60 - resilience: - enableRetries: true - retryDelays: - - "00:00:01" - - "00:00:02" - - "00:00:05" - allowOfflineCacheFallback: true - offlineCacheTolerance: "00:10:00" -``` - -> Store secrets outside source control. Concelier reads `clientSecretFile` on startup; rotate by updating the mounted file and restarting the service. - -### Resilience tuning - -- **Connected sites:** keep the default 1 s / 2 s / 5 s retry ladder so Concelier retries transient Authority hiccups but still surfaces outages quickly. Leave `allowOfflineCacheFallback=true` so cached discovery/JWKS data can bridge short Pathfinder restarts. -- **Air-gapped/Offline Kit installs:** extend `offlineCacheTolerance` (15–30 minutes) to keep the cached metadata valid between manual synchronisations. You can also disable retries (`enableRetries=false`) if infrastructure teams prefer to handle exponential backoff at the network layer; Concelier will fail fast but keep deterministic logs. -- Concelier resolves these knobs through `IOptionsMonitor`. Edits to `concelier.yaml` are applied on configuration reload; restart the container if you change environment variables or do not have file-watch reloads enabled. - -## 2. Key Signals - -### 2.1 Audit log channel - -Concelier emits structured audit entries via the `Concelier.Authorization.Audit` logger for every `/jobs*` request once Authority enforcement is active. - -``` -Concelier authorization audit route=/jobs/definitions status=200 subject=ops@example.com clientId=concelier-cli scopes=concelier.jobs.trigger advisory:ingest bypass=False remote=10.1.4.7 -``` - -| Field | Sample value | Meaning | -|--------------|-------------------------|------------------------------------------------------------------------------------------| -| `route` | `/jobs/definitions` | Endpoint that processed the request. | -| `status` | `200` / `401` / `409` | Final HTTP status code returned to the caller. | -| `subject` | `ops@example.com` | User or service principal subject (falls back to `(anonymous)` when unauthenticated). | -| `clientId` | `concelier-cli` | OAuth client ID provided by Authority (`(none)` if the token lacked the claim). | -| `scopes` | `concelier.jobs.trigger advisory:ingest advisory:read` | Normalised scope list extracted from token claims; `(none)` if the token carried none. | -| `tenant` | `tenant-default` | Tenant claim extracted from the Authority token (`(none)` when the token lacked it). | -| `bypass` | `True` / `False` | Indicates whether the request succeeded because its source IP matched a bypass CIDR. | -| `remote` | `10.1.4.7` | Remote IP recorded from the connection / forwarded header test hooks. | - -Use your logging backend (e.g., Loki) to index the logger name and filter for suspicious combinations: - -- `status=401 AND bypass=True` – bypass network accepted an unauthenticated call (should be temporary during rollout). -- `status=202 AND scopes="(none)"` – a token without scopes triggered a job; tighten client configuration. -- `status=202 AND NOT contains(scopes,"advisory:ingest")` – ingestion attempted without the new AOC scopes; confirm the Authority client registration matches the sample above. -- `tenant!=(tenant-default)` – indicates a cross-tenant token was accepted. Ensure Concelier `requiredTenants` is aligned with Authority client registration. -- Spike in `clientId="(none)"` – indicates upstream Authority is not issuing `client_id` claims or the CLI is outdated. - -### 2.2 Metrics - -Concelier publishes counters under the OTEL meter `StellaOps.Concelier.WebService.Jobs`. Tags: `job.kind`, `job.trigger`, `job.outcome`. - -| Metric name | Description | PromQL example | -|-------------------------------|----------------------------------------------------|----------------| -| `web.jobs.triggered` | Accepted job trigger requests. | `sum by (job_kind) (rate(web_jobs_triggered_total[5m]))` | -| `web.jobs.trigger.conflict` | Rejected triggers (already running, disabled…). | `sum(rate(web_jobs_trigger_conflict_total[5m]))` | -| `web.jobs.trigger.failed` | Server-side job failures. | `sum(rate(web_jobs_trigger_failed_total[5m]))` | - -> Prometheus/OTEL collectors typically surface counters with `_total` suffix. Adjust queries to match your pipeline’s generated metric names. - -Correlate audit logs with the following global meter exported via `Concelier.SourceDiagnostics`: - -- `concelier.source.http.requests_total{concelier_source="jobs-run"}` – ensures REST/manual triggers route through Authority. -- If Grafana dashboards are deployed, extend the “Concelier Jobs” board with the above counters plus a table of recent audit log entries. - -## 3. Alerting Guidance - -1. **Unauthorized bypass attempt** - - Query: `sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", status="401", bypass="True"}[5m])) > 0` - - Action: verify `bypassNetworks` list; confirm expected maintenance windows; rotate credentials if suspicious. - -2. **Missing scopes** - - Query: `sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", scopes="(none)", status="200"}[5m])) > 0` - - Action: audit Authority client registration; ensure `requiredScopes` includes `concelier.jobs.trigger`, `advisory:ingest`, and `advisory:read`. - -3. **Trigger failure surge** - - Query: `sum(rate(web_jobs_trigger_failed_total[10m])) > 0` with severity `warning` if sustained for 10 minutes. - - Action: inspect correlated audit entries and `Concelier.Telemetry` traces for job execution errors. - -4. **Conflict spike** - - Query: `sum(rate(web_jobs_trigger_conflict_total[10m])) > 5` (tune threshold). - - Action: downstream scheduling may be firing repetitive triggers; ensure precedence is configured properly. - -5. **Authority offline** - - Watch `Concelier.Authorization.Audit` logs for `status=503` or `status=500` along with `clientId="(none)"`. Investigate Authority availability before re-enabling anonymous fallback. - -## 4. Rollout & Verification Procedure - -1. **Pre-checks** - - Align with the rollout phases documented in `docs/10_CONCELIER_CLI_QUICKSTART.md` (validation → rehearsal → enforced) and record the target dates in your change request. - - Confirm `allowAnonymousFallback` is `false` in production; keep `true` only during staged validation. - - Validate Authority issuer metadata is reachable from Concelier (`curl https://authority.internal/.well-known/openid-configuration` from the host). - -2. **Smoke test with valid token** - - Obtain a token via CLI: `stella auth login --scope "concelier.jobs.trigger advisory:ingest" --scope advisory:read`. - - Trigger a read-only endpoint: `curl -H "Authorization: Bearer $TOKEN" https://concelier.internal/jobs/definitions`. - - Expect HTTP 200/202 and an audit log with `bypass=False`, `scopes=concelier.jobs.trigger advisory:ingest advisory:read`, and `tenant=tenant-default`. - -3. **Negative test without token** - - Call the same endpoint without a token. Expect HTTP 401, `bypass=False`. - - If the request succeeds, double-check `bypassNetworks` and ensure fallback is disabled. - -4. **Bypass check (if applicable)** - - From an allowed maintenance IP, call `/jobs/definitions` without a token. Confirm the audit log shows `bypass=True`. Review business justification and expiry date for such entries. - -5. **Metrics validation** - - Ensure `web.jobs.triggered` counter increments during accepted runs. - - Exporters should show corresponding spans (`concelier.job.trigger`) if tracing is enabled. - -## 5. Troubleshooting - -| Symptom | Probable cause | Remediation | -|---------|----------------|-------------| -| Audit log shows `clientId=(none)` for all requests | Authority not issuing `client_id` claim or CLI outdated | Update StellaOps Authority configuration (`StellaOpsAuthorityOptions.Token.Claims.ClientId`), or upgrade the CLI token acquisition flow. | -| Requests succeed with `bypass=True` unexpectedly | Local network added to `bypassNetworks` or fallback still enabled | Remove/adjust the CIDR list, disable anonymous fallback, restart Concelier. | -| HTTP 401 with valid token | `requiredScopes` missing from client registration or token audience mismatch | Verify Authority client scopes (`concelier.jobs.trigger`) and ensure the token audience matches `audiences` config. | -| Metrics missing from Prometheus | Telemetry exporters disabled or filter missing OTEL meter | Set `concelier.telemetry.enableMetrics=true`, ensure collector includes `StellaOps.Concelier.WebService.Jobs` meter. | -| Sudden spike in `web.jobs.trigger.failed` | Downstream job failure or Authority timeout mid-request | Inspect Concelier job logs, re-run with tracing enabled, validate Authority latency. | - -## 6. References - -- `docs/21_INSTALL_GUIDE.md` – Authority configuration quick start. -- `docs/17_SECURITY_HARDENING_GUIDE.md` – Security guardrails and enforcement deadlines. -- `docs/ops/authority-monitoring.md` – Authority-side monitoring and alerting playbook. -- `StellaOps.Concelier.WebService/Filters/JobAuthorizationAuditFilter.cs` – source of audit log fields. +# Concelier Authority Audit Runbook + +_Last updated: 2025-10-22_ + +This runbook helps operators verify and monitor the StellaOps Concelier ⇆ Authority integration. It focuses on the `/jobs*` surface, which now requires StellaOps Authority tokens, and the corresponding audit/metric signals that expose authentication and bypass activity. + +## 1. Prerequisites + +- Authority integration is enabled in `concelier.yaml` (or via `CONCELIER_AUTHORITY__*` environment variables) with a valid `clientId`, secret, audience, and required scopes. +- OTLP metrics/log exporters are configured (`concelier.telemetry.*`) or container stdout is shipped to your SIEM. +- Operators have access to the Concelier job trigger endpoints via CLI or REST for smoke tests. +- The rollout table in `docs/10_CONCELIER_CLI_QUICKSTART.md` has been reviewed so stakeholders align on the staged → enforced toggle timeline. + +### Configuration snippet + +```yaml +concelier: + authority: + enabled: true + allowAnonymousFallback: false # keep true only during initial rollout + issuer: "https://authority.internal" + audiences: + - "api://concelier" + requiredScopes: + - "concelier.jobs.trigger" + - "advisory:read" + - "advisory:ingest" + requiredTenants: + - "tenant-default" + bypassNetworks: + - "127.0.0.1/32" + - "::1/128" + clientId: "concelier-jobs" + clientSecretFile: "/run/secrets/concelier_authority_client" + tokenClockSkewSeconds: 60 + resilience: + enableRetries: true + retryDelays: + - "00:00:01" + - "00:00:02" + - "00:00:05" + allowOfflineCacheFallback: true + offlineCacheTolerance: "00:10:00" +``` + +> Store secrets outside source control. Concelier reads `clientSecretFile` on startup; rotate by updating the mounted file and restarting the service. + +### Resilience tuning + +- **Connected sites:** keep the default 1 s / 2 s / 5 s retry ladder so Concelier retries transient Authority hiccups but still surfaces outages quickly. Leave `allowOfflineCacheFallback=true` so cached discovery/JWKS data can bridge short Pathfinder restarts. +- **Air-gapped/Offline Kit installs:** extend `offlineCacheTolerance` (15–30 minutes) to keep the cached metadata valid between manual synchronisations. You can also disable retries (`enableRetries=false`) if infrastructure teams prefer to handle exponential backoff at the network layer; Concelier will fail fast but keep deterministic logs. +- Concelier resolves these knobs through `IOptionsMonitor`. Edits to `concelier.yaml` are applied on configuration reload; restart the container if you change environment variables or do not have file-watch reloads enabled. + +## 2. Key Signals + +### 2.1 Audit log channel + +Concelier emits structured audit entries via the `Concelier.Authorization.Audit` logger for every `/jobs*` request once Authority enforcement is active. + +``` +Concelier authorization audit route=/jobs/definitions status=200 subject=ops@example.com clientId=concelier-cli scopes=concelier.jobs.trigger advisory:ingest bypass=False remote=10.1.4.7 +``` + +| Field | Sample value | Meaning | +|--------------|-------------------------|------------------------------------------------------------------------------------------| +| `route` | `/jobs/definitions` | Endpoint that processed the request. | +| `status` | `200` / `401` / `409` | Final HTTP status code returned to the caller. | +| `subject` | `ops@example.com` | User or service principal subject (falls back to `(anonymous)` when unauthenticated). | +| `clientId` | `concelier-cli` | OAuth client ID provided by Authority (`(none)` if the token lacked the claim). | +| `scopes` | `concelier.jobs.trigger advisory:ingest advisory:read` | Normalised scope list extracted from token claims; `(none)` if the token carried none. | +| `tenant` | `tenant-default` | Tenant claim extracted from the Authority token (`(none)` when the token lacked it). | +| `bypass` | `True` / `False` | Indicates whether the request succeeded because its source IP matched a bypass CIDR. | +| `remote` | `10.1.4.7` | Remote IP recorded from the connection / forwarded header test hooks. | + +Use your logging backend (e.g., Loki) to index the logger name and filter for suspicious combinations: + +- `status=401 AND bypass=True` – bypass network accepted an unauthenticated call (should be temporary during rollout). +- `status=202 AND scopes="(none)"` – a token without scopes triggered a job; tighten client configuration. +- `status=202 AND NOT contains(scopes,"advisory:ingest")` – ingestion attempted without the new AOC scopes; confirm the Authority client registration matches the sample above. +- `tenant!=(tenant-default)` – indicates a cross-tenant token was accepted. Ensure Concelier `requiredTenants` is aligned with Authority client registration. +- Spike in `clientId="(none)"` – indicates upstream Authority is not issuing `client_id` claims or the CLI is outdated. + +### 2.2 Metrics + +Concelier publishes counters under the OTEL meter `StellaOps.Concelier.WebService.Jobs`. Tags: `job.kind`, `job.trigger`, `job.outcome`. + +| Metric name | Description | PromQL example | +|-------------------------------|----------------------------------------------------|----------------| +| `web.jobs.triggered` | Accepted job trigger requests. | `sum by (job_kind) (rate(web_jobs_triggered_total[5m]))` | +| `web.jobs.trigger.conflict` | Rejected triggers (already running, disabled…). | `sum(rate(web_jobs_trigger_conflict_total[5m]))` | +| `web.jobs.trigger.failed` | Server-side job failures. | `sum(rate(web_jobs_trigger_failed_total[5m]))` | + +> Prometheus/OTEL collectors typically surface counters with `_total` suffix. Adjust queries to match your pipeline’s generated metric names. + +Correlate audit logs with the following global meter exported via `Concelier.SourceDiagnostics`: + +- `concelier.source.http.requests_total{concelier_source="jobs-run"}` – ensures REST/manual triggers route through Authority. +- If Grafana dashboards are deployed, extend the “Concelier Jobs” board with the above counters plus a table of recent audit log entries. + +## 3. Alerting Guidance + +1. **Unauthorized bypass attempt** + - Query: `sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", status="401", bypass="True"}[5m])) > 0` + - Action: verify `bypassNetworks` list; confirm expected maintenance windows; rotate credentials if suspicious. + +2. **Missing scopes** + - Query: `sum(rate(log_messages_total{logger="Concelier.Authorization.Audit", scopes="(none)", status="200"}[5m])) > 0` + - Action: audit Authority client registration; ensure `requiredScopes` includes `concelier.jobs.trigger`, `advisory:ingest`, and `advisory:read`. + +3. **Trigger failure surge** + - Query: `sum(rate(web_jobs_trigger_failed_total[10m])) > 0` with severity `warning` if sustained for 10 minutes. + - Action: inspect correlated audit entries and `Concelier.Telemetry` traces for job execution errors. + +4. **Conflict spike** + - Query: `sum(rate(web_jobs_trigger_conflict_total[10m])) > 5` (tune threshold). + - Action: downstream scheduling may be firing repetitive triggers; ensure precedence is configured properly. + +5. **Authority offline** + - Watch `Concelier.Authorization.Audit` logs for `status=503` or `status=500` along with `clientId="(none)"`. Investigate Authority availability before re-enabling anonymous fallback. + +## 4. Rollout & Verification Procedure + +1. **Pre-checks** + - Align with the rollout phases documented in `docs/10_CONCELIER_CLI_QUICKSTART.md` (validation → rehearsal → enforced) and record the target dates in your change request. + - Confirm `allowAnonymousFallback` is `false` in production; keep `true` only during staged validation. + - Validate Authority issuer metadata is reachable from Concelier (`curl https://authority.internal/.well-known/openid-configuration` from the host). + +2. **Smoke test with valid token** + - Obtain a token via CLI: `stella auth login --scope "concelier.jobs.trigger advisory:ingest" --scope advisory:read`. + - Trigger a read-only endpoint: `curl -H "Authorization: Bearer $TOKEN" https://concelier.internal/jobs/definitions`. + - Expect HTTP 200/202 and an audit log with `bypass=False`, `scopes=concelier.jobs.trigger advisory:ingest advisory:read`, and `tenant=tenant-default`. + +3. **Negative test without token** + - Call the same endpoint without a token. Expect HTTP 401, `bypass=False`. + - If the request succeeds, double-check `bypassNetworks` and ensure fallback is disabled. + +4. **Bypass check (if applicable)** + - From an allowed maintenance IP, call `/jobs/definitions` without a token. Confirm the audit log shows `bypass=True`. Review business justification and expiry date for such entries. + +5. **Metrics validation** + - Ensure `web.jobs.triggered` counter increments during accepted runs. + - Exporters should show corresponding spans (`concelier.job.trigger`) if tracing is enabled. + +## 5. Troubleshooting + +| Symptom | Probable cause | Remediation | +|---------|----------------|-------------| +| Audit log shows `clientId=(none)` for all requests | Authority not issuing `client_id` claim or CLI outdated | Update StellaOps Authority configuration (`StellaOpsAuthorityOptions.Token.Claims.ClientId`), or upgrade the CLI token acquisition flow. | +| Requests succeed with `bypass=True` unexpectedly | Local network added to `bypassNetworks` or fallback still enabled | Remove/adjust the CIDR list, disable anonymous fallback, restart Concelier. | +| HTTP 401 with valid token | `requiredScopes` missing from client registration or token audience mismatch | Verify Authority client scopes (`concelier.jobs.trigger`) and ensure the token audience matches `audiences` config. | +| Metrics missing from Prometheus | Telemetry exporters disabled or filter missing OTEL meter | Set `concelier.telemetry.enableMetrics=true`, ensure collector includes `StellaOps.Concelier.WebService.Jobs` meter. | +| Sudden spike in `web.jobs.trigger.failed` | Downstream job failure or Authority timeout mid-request | Inspect Concelier job logs, re-run with tracing enabled, validate Authority latency. | + +## 6. References + +- `docs/21_INSTALL_GUIDE.md` – Authority configuration quick start. +- `docs/17_SECURITY_HARDENING_GUIDE.md` – Security guardrails and enforcement deadlines. +- `docs/modules/authority/operations/monitoring.md` – Authority-side monitoring and alerting playbook. +- `StellaOps.Concelier.WebService/Filters/JobAuthorizationAuditFilter.cs` – source of audit log fields. diff --git a/docs/ops/concelier-conflict-resolution.md b/docs/modules/concelier/operations/conflict-resolution.md similarity index 100% rename from docs/ops/concelier-conflict-resolution.md rename to docs/modules/concelier/operations/conflict-resolution.md diff --git a/docs/ops/concelier-apple-operations.md b/docs/modules/concelier/operations/connectors/apple.md similarity index 100% rename from docs/ops/concelier-apple-operations.md rename to docs/modules/concelier/operations/connectors/apple.md diff --git a/docs/ops/concelier-cccs-operations.md b/docs/modules/concelier/operations/connectors/cccs.md similarity index 100% rename from docs/ops/concelier-cccs-operations.md rename to docs/modules/concelier/operations/connectors/cccs.md diff --git a/docs/ops/concelier-certbund-operations.md b/docs/modules/concelier/operations/connectors/certbund.md similarity index 95% rename from docs/ops/concelier-certbund-operations.md rename to docs/modules/concelier/operations/connectors/certbund.md index ab16503e..bd5e8db4 100644 --- a/docs/ops/concelier-certbund-operations.md +++ b/docs/modules/concelier/operations/connectors/certbund.md @@ -96,7 +96,7 @@ curl -s -b cookies.txt \ Iterate `page` until the response `content` array is empty. Pages 0–9 currently cover 2014→present. Persist JSON responses (plus SHA256) for Offline Kit parity. -> **Shortcut** – run `python tools/certbund_offline_snapshot.py --output seed-data/cert-bund` +> **Shortcut** – run `python src/Tools/certbund_offline_snapshot.py --output seed-data/cert-bund` > to bootstrap the session, capture the paginated search responses, and regenerate > the manifest/checksum files automatically. Supply `--cookie-file` and `--xsrf-token` > if the portal requires a browser-derived session (see options via `--help`). @@ -104,7 +104,7 @@ Iterate `page` until the response `content` array is empty. Pages 0–9 currentl ### 3.3 Export bundles ```bash -python tools/certbund_offline_snapshot.py \ +python src/Tools/certbund_offline_snapshot.py \ --output seed-data/cert-bund \ --start-year 2014 \ --end-year "$(date -u +%Y)" diff --git a/docs/ops/concelier-cisco-operations.md b/docs/modules/concelier/operations/connectors/cisco.md similarity index 100% rename from docs/ops/concelier-cisco-operations.md rename to docs/modules/concelier/operations/connectors/cisco.md diff --git a/docs/ops/concelier-cve-kev-grafana-dashboard.json b/docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json similarity index 100% rename from docs/ops/concelier-cve-kev-grafana-dashboard.json rename to docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json diff --git a/docs/ops/concelier-cve-kev-operations.md b/docs/modules/concelier/operations/connectors/cve-kev.md similarity index 94% rename from docs/ops/concelier-cve-kev-operations.md rename to docs/modules/concelier/operations/connectors/cve-kev.md index cf5afe9c..4b24e722 100644 --- a/docs/ops/concelier-cve-kev-operations.md +++ b/docs/modules/concelier/operations/connectors/cve-kev.md @@ -51,7 +51,7 @@ concelier: - `rate(cve_map_success_total[15m]) == 0` while `rate(cve_fetch_success_total[15m]) > 0` (`severity=critical`) - `sum_over_time(cve_parse_quarantine_total[1h]) > 0` to catch schema anomalies - **Logs** – Monitor warnings such as `Failed fetching CVE record {CveId}` and `Malformed CVE JSON`, and surface the summary info log `CVEs fetch window … detailFailures=0 detailUnchanged=0` on dashboards. A non-zero `detailFailures` usually indicates rate-limit or auth issues on detail requests. -- **Grafana pack** – Import `docs/ops/concelier-cve-kev-grafana-dashboard.json` and filter by panel legend (`CVE`, `KEV`) to reuse the canned layout. +- **Grafana pack** – Import `docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json` and filter by panel legend (`CVE`, `KEV`) to reuse the canned layout. - **Backfill window** – Operators can tighten or widen `initialBackfill` / `maxPagesPerFetch` after validating throughput. Update config and restart Concelier to apply changes. ### 1.4 Staging smoke log (2025-10-15) @@ -72,7 +72,7 @@ While Ops finalises long-lived CVE Services credentials, we validated the connec | `cve.parse.success` | 1 | | `cve.map.success` | 1 | -The Grafana pack `docs/ops/concelier-cve-kev-grafana-dashboard.json` has been imported into staging so the panels referenced above render against these counters once the live API keys are in place. +The Grafana pack `docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json` has been imported into staging so the panels referenced above render against these counters once the live API keys are in place. ## 2. CISA KEV Connector (`source:kev:*`) @@ -140,4 +140,4 @@ Add the following panels to the Concelier observability board: - Record staging/production smoke test results (date, catalog version, advisory counts) in your team’s change log. - Add the CVE/KEV job kinds to the standard maintenance checklist so operators can manually trigger them after planned downtime. - Keep this document in sync with future connector changes (for example, new anomaly reasons or additional metrics). -- Version-control dashboard tweaks alongside `docs/ops/concelier-cve-kev-grafana-dashboard.json` so operations can re-import the observability pack during restores. +- Version-control dashboard tweaks alongside `docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json` so operations can re-import the observability pack during restores. diff --git a/docs/ops/concelier-ghsa-operations.md b/docs/modules/concelier/operations/connectors/ghsa.md similarity index 100% rename from docs/ops/concelier-ghsa-operations.md rename to docs/modules/concelier/operations/connectors/ghsa.md diff --git a/docs/ops/concelier-icscisa-operations.md b/docs/modules/concelier/operations/connectors/ics-cisa.md similarity index 100% rename from docs/ops/concelier-icscisa-operations.md rename to docs/modules/concelier/operations/connectors/ics-cisa.md diff --git a/docs/ops/concelier-kisa-operations.md b/docs/modules/concelier/operations/connectors/kisa.md similarity index 100% rename from docs/ops/concelier-kisa-operations.md rename to docs/modules/concelier/operations/connectors/kisa.md diff --git a/docs/ops/concelier-msrc-operations.md b/docs/modules/concelier/operations/connectors/msrc.md similarity index 91% rename from docs/ops/concelier-msrc-operations.md rename to docs/modules/concelier/operations/connectors/msrc.md index e91aa25c..6c4f7957 100644 --- a/docs/ops/concelier-msrc-operations.md +++ b/docs/modules/concelier/operations/connectors/msrc.md @@ -41,7 +41,7 @@ concelier: ### 4.1 State seeding helper -Use `tools/SourceStateSeeder` to queue historical advisories (detail JSON + optional CVRF artefacts) for replay without manual Mongo edits. Example seed file: +Use `src/Tools/SourceStateSeeder` to queue historical advisories (detail JSON + optional CVRF artefacts) for replay without manual Mongo edits. Example seed file: ```json { @@ -71,7 +71,7 @@ Use `tools/SourceStateSeeder` to queue historical advisories (detail JSON + opti Run the helper: ```bash -dotnet run --project tools/SourceStateSeeder -- \ +dotnet run --project src/Tools/SourceStateSeeder -- \ --connection-string "mongodb://localhost:27017" \ --database concelier \ --input seeds/msrc-backfill.json diff --git a/docs/ops/concelier-nkcki-operations.md b/docs/modules/concelier/operations/connectors/nkcki.md similarity index 97% rename from docs/ops/concelier-nkcki-operations.md rename to docs/modules/concelier/operations/connectors/nkcki.md index 2559c216..8fe453d4 100644 --- a/docs/ops/concelier-nkcki-operations.md +++ b/docs/modules/concelier/operations/connectors/nkcki.md @@ -43,6 +43,6 @@ For large migrations, seed caches with archived zip bundles, then run fetch/pars - Listing failures mark the source state with exponential backoff while attempting cache replay. - Bulletin fetches fall back to cached copies before surfacing an error. -- Mongo integration tests rely on bundled OpenSSL 1.1 libraries (`tools/openssl/linux-x64`) to keep `Mongo2Go` operational on modern distros. +- Mongo integration tests rely on bundled OpenSSL 1.1 libraries (`src/Tools/openssl/linux-x64`) to keep `Mongo2Go` operational on modern distros. Refer to `ru-nkcki` entries in `src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ru.Nkcki/TASKS.md` for outstanding items. diff --git a/docs/ops/concelier-osv-operations.md b/docs/modules/concelier/operations/connectors/osv.md similarity index 100% rename from docs/ops/concelier-osv-operations.md rename to docs/modules/concelier/operations/connectors/osv.md diff --git a/docs/ops/concelier-mirror-operations.md b/docs/modules/concelier/operations/mirror.md similarity index 96% rename from docs/ops/concelier-mirror-operations.md rename to docs/modules/concelier/operations/mirror.md index 77af169c..46cb4158 100644 --- a/docs/ops/concelier-mirror-operations.md +++ b/docs/modules/concelier/operations/mirror.md @@ -1,238 +1,238 @@ -# Concelier & Excititor Mirror Operations - -This runbook describes how Stella Ops operates the managed mirrors under `*.stella-ops.org`. -It covers Docker Compose and Helm deployment overlays, secret handling for multi-tenant -authn, CDN fronting, and the recurring sync pipeline that keeps mirror bundles current. - -## 1. Prerequisites - -- **Authority access** – client credentials (`client_id` + secret) authorised for - `concelier.mirror.read` and `excititor.mirror.read` scopes. Secrets live outside git. -- **Signed TLS certificates** – wildcard or per-domain (`mirror-primary`, `mirror-community`). - Store them under `deploy/compose/mirror-gateway/tls/` or in Kubernetes secrets. -- **Mirror gateway credentials** – Basic Auth htpasswd files per domain. Generate with - `htpasswd -B`. Operators distribute credentials to downstream consumers. -- **Export artifact source** – read access to the canonical S3 buckets (or rsync share) - that hold `concelier` JSON bundles and `excititor` VEX exports. -- **Persistent volumes** – storage for Concelier job metadata and mirror export trees. - For Helm, provision PVCs (`concelier-mirror-jobs`, `concelier-mirror-exports`, - `excititor-mirror-exports`, `mirror-mongo-data`, `mirror-minio-data`) before rollout. - -### 1.1 Service configuration quick reference - -Concelier.WebService exposes the mirror HTTP endpoints once `CONCELIER__MIRROR__ENABLED=true`. -Key knobs: - -- `CONCELIER__MIRROR__EXPORTROOT` – root folder containing export snapshots (`/mirror/*`). -- `CONCELIER__MIRROR__ACTIVEEXPORTID` – optional explicit export id; otherwise the service auto-falls back to the `latest/` symlink or newest directory. -- `CONCELIER__MIRROR__REQUIREAUTHENTICATION` – default auth requirement; override per domain with `CONCELIER__MIRROR__DOMAINS__{n}__REQUIREAUTHENTICATION`. -- `CONCELIER__MIRROR__MAXINDEXREQUESTSPERHOUR` – budget for `/concelier/exports/index.json`. Domains inherit this value unless they define `__MAXDOWNLOADREQUESTSPERHOUR`. -- `CONCELIER__MIRROR__DOMAINS__{n}__ID` – domain identifier matching the exporter manifest; additional keys configure display name and rate budgets. - -> The service honours Stella Ops Authority when `CONCELIER__AUTHORITY__ENABLED=true` and `ALLOWANONYMOUSFALLBACK=false`. Use the bypass CIDR list (`CONCELIER__AUTHORITY__BYPASSNETWORKS__*`) for in-cluster ingress gateways that terminate Basic Auth. Unauthorized requests emit `WWW-Authenticate: Bearer` so downstream automation can detect token failures. - -Mirror responses carry deterministic cache headers: `/index.json` returns `Cache-Control: public, max-age=60`, while per-domain manifests/bundles include `Cache-Control: public, max-age=300, immutable`. Rate limiting surfaces `Retry-After` when quotas are exceeded. - -### 1.2 Mirror connector configuration - -Downstream Concelier instances ingest published bundles using the `StellaOpsMirrorConnector`. Operators running the connector in air‑gapped or limited connectivity environments can tune the following options (environment prefix `CONCELIER__SOURCES__STELLAOPSMIRROR__`): - -- `BASEADDRESS` – absolute mirror root (e.g., `https://mirror-primary.stella-ops.org`). -- `INDEXPATH` – relative path to the mirror index (`/concelier/exports/index.json` by default). -- `DOMAINID` – mirror domain identifier from the index (`primary`, `community`, etc.). -- `HTTPTIMEOUT` – request timeout; raise when mirrors sit behind slow WAN links. -- `SIGNATURE__ENABLED` – require detached JWS verification for `bundle.json`. -- `SIGNATURE__KEYID` / `SIGNATURE__PROVIDER` – expected signing key metadata. -- `SIGNATURE__PUBLICKEYPATH` – PEM fallback used when the mirror key registry is offline. - -The connector keeps a per-export fingerprint (bundle digest + generated-at timestamp) and tracks outstanding document IDs. If a scan is interrupted, the next run resumes parse/map work using the stored fingerprint and pending document lists—no network requests are reissued unless the upstream digest changes. - -## 2. Secret & certificate layout - -### Docker Compose (`deploy/compose/docker-compose.mirror.yaml`) - -- `deploy/compose/env/mirror.env.example` – copy to `.env` and adjust quotas or domain IDs. -- `deploy/compose/mirror-secrets/` – mount read-only into `/run/secrets`. Place: - - `concelier-authority-client` – Authority client secret. - - `excititor-authority-client` (optional) – reserve for future authn. -- `deploy/compose/mirror-gateway/tls/` – PEM-encoded cert/key pairs: - - `mirror-primary.crt`, `mirror-primary.key` - - `mirror-community.crt`, `mirror-community.key` -- `deploy/compose/mirror-gateway/secrets/` – htpasswd files: - - `mirror-primary.htpasswd` - - `mirror-community.htpasswd` - -### Helm (`deploy/helm/stellaops/values-mirror.yaml`) - -Create secrets in the target namespace: - -```bash -kubectl create secret generic concelier-mirror-auth \ - --from-file=concelier-authority-client=concelier-authority-client - -kubectl create secret generic excititor-mirror-auth \ - --from-file=excititor-authority-client=excititor-authority-client - -kubectl create secret tls mirror-gateway-tls \ - --cert=mirror-primary.crt --key=mirror-primary.key - -kubectl create secret generic mirror-gateway-htpasswd \ - --from-file=mirror-primary.htpasswd --from-file=mirror-community.htpasswd -``` - -> Keep Basic Auth lists short-lived (rotate quarterly) and document credential recipients. - -## 3. Deployment - -### 3.1 Docker Compose (edge mirrors, lab validation) - -1. `cp deploy/compose/env/mirror.env.example deploy/compose/env/mirror.env` -2. Populate secrets/tls directories as described above. -3. Sync mirror bundles (see §4) into `deploy/compose/mirror-data/…` and ensure they are mounted - on the host path backing the `concelier-exports` and `excititor-exports` volumes. -4. Run the profile validator: `deploy/tools/validate-profiles.sh`. -5. Launch: `docker compose --env-file env/mirror.env -f docker-compose.mirror.yaml up -d`. - -### 3.2 Helm (production mirrors) - -1. Provision PVCs sized for mirror bundles (baseline: 20 GiB per domain). -2. Create secrets/tls config maps (§2). -3. `helm upgrade --install mirror deploy/helm/stellaops -f deploy/helm/stellaops/values-mirror.yaml`. -4. Annotate the `stellaops-mirror-gateway` service with ingress/LoadBalancer metadata required by - your CDN (e.g., AWS load balancer scheme internal + NLB idle timeout). - -## 4. Artifact sync workflow - -Mirrors never generate exports—they ingest signed bundles produced by the Concelier and Excititor -export jobs. Recommended sync pattern: - -### 4.1 Compose host (systemd timer) - -`/usr/local/bin/mirror-sync.sh`: - -```bash -#!/usr/bin/env bash -set -euo pipefail -export AWS_ACCESS_KEY_ID=… -export AWS_SECRET_ACCESS_KEY=… - -aws s3 sync s3://mirror-stellaops/concelier/latest \ - /opt/stellaops/mirror-data/concelier --delete --size-only - -aws s3 sync s3://mirror-stellaops/excititor/latest \ - /opt/stellaops/mirror-data/excititor --delete --size-only -``` - -Schedule with a systemd timer every 5 minutes. The Compose volumes mount `/opt/stellaops/mirror-data/*` -into the containers read-only, matching `CONCELIER__MIRROR__EXPORTROOT=/exports/json` and -`EXCITITOR__ARTIFACTS__FILESYSTEM__ROOT=/exports`. - -### 4.2 Kubernetes (CronJob) - -Create a CronJob running the AWS CLI (or rclone) in the same namespace, writing into the PVCs: - -```yaml -apiVersion: batch/v1 -kind: CronJob -metadata: - name: mirror-sync -spec: - schedule: "*/5 * * * *" - jobTemplate: - spec: - template: - spec: - containers: - - name: sync - image: public.ecr.aws/aws-cli/aws-cli@sha256:5df5f52c29f5e3ba46d0ad9e0e3afc98701c4a0f879400b4c5f80d943b5fadea - command: - - /bin/sh - - -c - - > - aws s3 sync s3://mirror-stellaops/concelier/latest /exports/concelier --delete --size-only && - aws s3 sync s3://mirror-stellaops/excititor/latest /exports/excititor --delete --size-only - volumeMounts: - - name: concelier-exports - mountPath: /exports/concelier - - name: excititor-exports - mountPath: /exports/excititor - envFrom: - - secretRef: - name: mirror-sync-aws - restartPolicy: OnFailure - volumes: - - name: concelier-exports - persistentVolumeClaim: - claimName: concelier-mirror-exports - - name: excititor-exports - persistentVolumeClaim: - claimName: excititor-mirror-exports -``` - -## 5. CDN integration - -1. Point the CDN origin at the mirror gateway (Compose host or Kubernetes LoadBalancer). -2. Honour the response headers emitted by the gateway and Concelier/Excititor: - `Cache-Control: public, max-age=300, immutable` for mirror payloads. -3. Configure origin shields in the CDN to prevent cache stampedes. Recommended TTLs: - - Index (`/concelier/exports/index.json`, `/excititor/mirror/*/index`) → 60 s. - - Bundle/manifest payloads → 300 s. -4. Forward the `Authorization` header—Basic Auth terminates at the gateway. -5. Enforce per-domain rate limits at the CDN (matching gateway budgets) and enable logging - to SIEM for anomaly detection. - -## 6. Smoke tests - -After each deployment or sync cycle (temporarily set low budgets if you need to observe 429 responses): - -```bash -# Index with Basic Auth -curl -u $PRIMARY_CREDS https://mirror-primary.stella-ops.org/concelier/exports/index.json | jq 'keys' - -# Mirror manifest signature and cache headers -curl -u $PRIMARY_CREDS -I https://mirror-primary.stella-ops.org/concelier/exports/mirror/primary/manifest.json \ - | tee /tmp/manifest-headers.txt -grep -E '^Cache-Control: ' /tmp/manifest-headers.txt # expect public, max-age=300, immutable - -# Excititor consensus bundle metadata -curl -u $COMMUNITY_CREDS https://mirror-community.stella-ops.org/excititor/mirror/community/index \ - | jq '.exports[].exportKey' - -# Signed bundle + detached JWS (spot check digests) -curl -u $PRIMARY_CREDS https://mirror-primary.stella-ops.org/concelier/exports/mirror/primary/bundle.json.jws \ - -o bundle.json.jws -cosign verify-blob --signature bundle.json.jws --key mirror-key.pub bundle.json - -# Service-level auth check (inside cluster – no gateway credentials) -kubectl exec deploy/stellaops-concelier -- curl -si http://localhost:8443/concelier/exports/mirror/primary/manifest.json \ - | head -n 5 # expect HTTP/1.1 401 with WWW-Authenticate: Bearer - -# Rate limit smoke (repeat quickly; second call should return 429 + Retry-After) -for i in 1 2; do - curl -s -o /dev/null -D - https://mirror-primary.stella-ops.org/concelier/exports/index.json \ - -u $PRIMARY_CREDS | grep -E '^(HTTP/|Retry-After:)' - sleep 1 -done -``` - -Watch the gateway metrics (`nginx_vts` or access logs) for cache hits. In Kubernetes, `kubectl logs deploy/stellaops-mirror-gateway` -should show `X-Cache-Status: HIT/MISS`. - -## 7. Maintenance & rotation - -- **Bundle freshness** – alert if sync job lag exceeds 15 minutes or if `concelier` logs - `Mirror export root is not configured`. -- **Secret rotation** – change Authority client secrets and Basic Auth credentials quarterly. - Update the mounted secrets and restart deployments (`docker compose restart concelier` or - `kubectl rollout restart deploy/stellaops-concelier`). -- **TLS renewal** – reissue certificates, place new files, and reload gateway (`docker compose exec mirror-gateway nginx -s reload`). -- **Quota tuning** – adjust per-domain `MAXDOWNLOADREQUESTSPERHOUR` in `.env` or values file. - Align CDN rate limits and inform downstreams. - -## 8. References - -- Deployment profiles: `deploy/compose/docker-compose.mirror.yaml`, - `deploy/helm/stellaops/values-mirror.yaml` -- Mirror architecture dossiers: `docs/ARCHITECTURE_CONCELIER.md`, - `docs/ARCHITECTURE_EXCITITOR_MIRRORS.md` -- Export bundling: `docs/ARCHITECTURE_DEVOPS.md` §3, `docs/ARCHITECTURE_EXCITITOR.md` §7 +# Concelier & Excititor Mirror Operations + +This runbook describes how Stella Ops operates the managed mirrors under `*.stella-ops.org`. +It covers Docker Compose and Helm deployment overlays, secret handling for multi-tenant +authn, CDN fronting, and the recurring sync pipeline that keeps mirror bundles current. + +## 1. Prerequisites + +- **Authority access** – client credentials (`client_id` + secret) authorised for + `concelier.mirror.read` and `excititor.mirror.read` scopes. Secrets live outside git. +- **Signed TLS certificates** – wildcard or per-domain (`mirror-primary`, `mirror-community`). + Store them under `deploy/compose/mirror-gateway/tls/` or in Kubernetes secrets. +- **Mirror gateway credentials** – Basic Auth htpasswd files per domain. Generate with + `htpasswd -B`. Operators distribute credentials to downstream consumers. +- **Export artifact source** – read access to the canonical S3 buckets (or rsync share) + that hold `concelier` JSON bundles and `excititor` VEX exports. +- **Persistent volumes** – storage for Concelier job metadata and mirror export trees. + For Helm, provision PVCs (`concelier-mirror-jobs`, `concelier-mirror-exports`, + `excititor-mirror-exports`, `mirror-mongo-data`, `mirror-minio-data`) before rollout. + +### 1.1 Service configuration quick reference + +Concelier.WebService exposes the mirror HTTP endpoints once `CONCELIER__MIRROR__ENABLED=true`. +Key knobs: + +- `CONCELIER__MIRROR__EXPORTROOT` – root folder containing export snapshots (`/mirror/*`). +- `CONCELIER__MIRROR__ACTIVEEXPORTID` – optional explicit export id; otherwise the service auto-falls back to the `latest/` symlink or newest directory. +- `CONCELIER__MIRROR__REQUIREAUTHENTICATION` – default auth requirement; override per domain with `CONCELIER__MIRROR__DOMAINS__{n}__REQUIREAUTHENTICATION`. +- `CONCELIER__MIRROR__MAXINDEXREQUESTSPERHOUR` – budget for `/concelier/exports/index.json`. Domains inherit this value unless they define `__MAXDOWNLOADREQUESTSPERHOUR`. +- `CONCELIER__MIRROR__DOMAINS__{n}__ID` – domain identifier matching the exporter manifest; additional keys configure display name and rate budgets. + +> The service honours Stella Ops Authority when `CONCELIER__AUTHORITY__ENABLED=true` and `ALLOWANONYMOUSFALLBACK=false`. Use the bypass CIDR list (`CONCELIER__AUTHORITY__BYPASSNETWORKS__*`) for in-cluster ingress gateways that terminate Basic Auth. Unauthorized requests emit `WWW-Authenticate: Bearer` so downstream automation can detect token failures. + +Mirror responses carry deterministic cache headers: `/index.json` returns `Cache-Control: public, max-age=60`, while per-domain manifests/bundles include `Cache-Control: public, max-age=300, immutable`. Rate limiting surfaces `Retry-After` when quotas are exceeded. + +### 1.2 Mirror connector configuration + +Downstream Concelier instances ingest published bundles using the `StellaOpsMirrorConnector`. Operators running the connector in air‑gapped or limited connectivity environments can tune the following options (environment prefix `CONCELIER__SOURCES__STELLAOPSMIRROR__`): + +- `BASEADDRESS` – absolute mirror root (e.g., `https://mirror-primary.stella-ops.org`). +- `INDEXPATH` – relative path to the mirror index (`/concelier/exports/index.json` by default). +- `DOMAINID` – mirror domain identifier from the index (`primary`, `community`, etc.). +- `HTTPTIMEOUT` – request timeout; raise when mirrors sit behind slow WAN links. +- `SIGNATURE__ENABLED` – require detached JWS verification for `bundle.json`. +- `SIGNATURE__KEYID` / `SIGNATURE__PROVIDER` – expected signing key metadata. +- `SIGNATURE__PUBLICKEYPATH` – PEM fallback used when the mirror key registry is offline. + +The connector keeps a per-export fingerprint (bundle digest + generated-at timestamp) and tracks outstanding document IDs. If a scan is interrupted, the next run resumes parse/map work using the stored fingerprint and pending document lists—no network requests are reissued unless the upstream digest changes. + +## 2. Secret & certificate layout + +### Docker Compose (`deploy/compose/docker-compose.mirror.yaml`) + +- `deploy/compose/env/mirror.env.example` – copy to `.env` and adjust quotas or domain IDs. +- `deploy/compose/mirror-secrets/` – mount read-only into `/run/secrets`. Place: + - `concelier-authority-client` – Authority client secret. + - `excititor-authority-client` (optional) – reserve for future authn. +- `deploy/compose/mirror-gateway/tls/` – PEM-encoded cert/key pairs: + - `mirror-primary.crt`, `mirror-primary.key` + - `mirror-community.crt`, `mirror-community.key` +- `deploy/compose/mirror-gateway/secrets/` – htpasswd files: + - `mirror-primary.htpasswd` + - `mirror-community.htpasswd` + +### Helm (`deploy/helm/stellaops/values-mirror.yaml`) + +Create secrets in the target namespace: + +```bash +kubectl create secret generic concelier-mirror-auth \ + --from-file=concelier-authority-client=concelier-authority-client + +kubectl create secret generic excititor-mirror-auth \ + --from-file=excititor-authority-client=excititor-authority-client + +kubectl create secret tls mirror-gateway-tls \ + --cert=mirror-primary.crt --key=mirror-primary.key + +kubectl create secret generic mirror-gateway-htpasswd \ + --from-file=mirror-primary.htpasswd --from-file=mirror-community.htpasswd +``` + +> Keep Basic Auth lists short-lived (rotate quarterly) and document credential recipients. + +## 3. Deployment + +### 3.1 Docker Compose (edge mirrors, lab validation) + +1. `cp deploy/compose/env/mirror.env.example deploy/compose/env/mirror.env` +2. Populate secrets/tls directories as described above. +3. Sync mirror bundles (see §4) into `deploy/compose/mirror-data/…` and ensure they are mounted + on the host path backing the `concelier-exports` and `excititor-exports` volumes. +4. Run the profile validator: `deploy/tools/validate-profiles.sh`. +5. Launch: `docker compose --env-file env/mirror.env -f docker-compose.mirror.yaml up -d`. + +### 3.2 Helm (production mirrors) + +1. Provision PVCs sized for mirror bundles (baseline: 20 GiB per domain). +2. Create secrets/tls config maps (§2). +3. `helm upgrade --install mirror deploy/helm/stellaops -f deploy/helm/stellaops/values-mirror.yaml`. +4. Annotate the `stellaops-mirror-gateway` service with ingress/LoadBalancer metadata required by + your CDN (e.g., AWS load balancer scheme internal + NLB idle timeout). + +## 4. Artifact sync workflow + +Mirrors never generate exports—they ingest signed bundles produced by the Concelier and Excititor +export jobs. Recommended sync pattern: + +### 4.1 Compose host (systemd timer) + +`/usr/local/bin/mirror-sync.sh`: + +```bash +#!/usr/bin/env bash +set -euo pipefail +export AWS_ACCESS_KEY_ID=… +export AWS_SECRET_ACCESS_KEY=… + +aws s3 sync s3://mirror-stellaops/concelier/latest \ + /opt/stellaops/mirror-data/concelier --delete --size-only + +aws s3 sync s3://mirror-stellaops/excititor/latest \ + /opt/stellaops/mirror-data/excititor --delete --size-only +``` + +Schedule with a systemd timer every 5 minutes. The Compose volumes mount `/opt/stellaops/mirror-data/*` +into the containers read-only, matching `CONCELIER__MIRROR__EXPORTROOT=/exports/json` and +`EXCITITOR__ARTIFACTS__FILESYSTEM__ROOT=/exports`. + +### 4.2 Kubernetes (CronJob) + +Create a CronJob running the AWS CLI (or rclone) in the same namespace, writing into the PVCs: + +```yaml +apiVersion: batch/v1 +kind: CronJob +metadata: + name: mirror-sync +spec: + schedule: "*/5 * * * *" + jobTemplate: + spec: + template: + spec: + containers: + - name: sync + image: public.ecr.aws/aws-cli/aws-cli@sha256:5df5f52c29f5e3ba46d0ad9e0e3afc98701c4a0f879400b4c5f80d943b5fadea + command: + - /bin/sh + - -c + - > + aws s3 sync s3://mirror-stellaops/concelier/latest /exports/concelier --delete --size-only && + aws s3 sync s3://mirror-stellaops/excititor/latest /exports/excititor --delete --size-only + volumeMounts: + - name: concelier-exports + mountPath: /exports/concelier + - name: excititor-exports + mountPath: /exports/excititor + envFrom: + - secretRef: + name: mirror-sync-aws + restartPolicy: OnFailure + volumes: + - name: concelier-exports + persistentVolumeClaim: + claimName: concelier-mirror-exports + - name: excititor-exports + persistentVolumeClaim: + claimName: excititor-mirror-exports +``` + +## 5. CDN integration + +1. Point the CDN origin at the mirror gateway (Compose host or Kubernetes LoadBalancer). +2. Honour the response headers emitted by the gateway and Concelier/Excititor: + `Cache-Control: public, max-age=300, immutable` for mirror payloads. +3. Configure origin shields in the CDN to prevent cache stampedes. Recommended TTLs: + - Index (`/concelier/exports/index.json`, `/excititor/mirror/*/index`) → 60 s. + - Bundle/manifest payloads → 300 s. +4. Forward the `Authorization` header—Basic Auth terminates at the gateway. +5. Enforce per-domain rate limits at the CDN (matching gateway budgets) and enable logging + to SIEM for anomaly detection. + +## 6. Smoke tests + +After each deployment or sync cycle (temporarily set low budgets if you need to observe 429 responses): + +```bash +# Index with Basic Auth +curl -u $PRIMARY_CREDS https://mirror-primary.stella-ops.org/concelier/exports/index.json | jq 'keys' + +# Mirror manifest signature and cache headers +curl -u $PRIMARY_CREDS -I https://mirror-primary.stella-ops.org/concelier/exports/mirror/primary/manifest.json \ + | tee /tmp/manifest-headers.txt +grep -E '^Cache-Control: ' /tmp/manifest-headers.txt # expect public, max-age=300, immutable + +# Excititor consensus bundle metadata +curl -u $COMMUNITY_CREDS https://mirror-community.stella-ops.org/excititor/mirror/community/index \ + | jq '.exports[].exportKey' + +# Signed bundle + detached JWS (spot check digests) +curl -u $PRIMARY_CREDS https://mirror-primary.stella-ops.org/concelier/exports/mirror/primary/bundle.json.jws \ + -o bundle.json.jws +cosign verify-blob --signature bundle.json.jws --key mirror-key.pub bundle.json + +# Service-level auth check (inside cluster – no gateway credentials) +kubectl exec deploy/stellaops-concelier -- curl -si http://localhost:8443/concelier/exports/mirror/primary/manifest.json \ + | head -n 5 # expect HTTP/1.1 401 with WWW-Authenticate: Bearer + +# Rate limit smoke (repeat quickly; second call should return 429 + Retry-After) +for i in 1 2; do + curl -s -o /dev/null -D - https://mirror-primary.stella-ops.org/concelier/exports/index.json \ + -u $PRIMARY_CREDS | grep -E '^(HTTP/|Retry-After:)' + sleep 1 +done +``` + +Watch the gateway metrics (`nginx_vts` or access logs) for cache hits. In Kubernetes, `kubectl logs deploy/stellaops-mirror-gateway` +should show `X-Cache-Status: HIT/MISS`. + +## 7. Maintenance & rotation + +- **Bundle freshness** – alert if sync job lag exceeds 15 minutes or if `concelier` logs + `Mirror export root is not configured`. +- **Secret rotation** – change Authority client secrets and Basic Auth credentials quarterly. + Update the mounted secrets and restart deployments (`docker compose restart concelier` or + `kubectl rollout restart deploy/stellaops-concelier`). +- **TLS renewal** – reissue certificates, place new files, and reload gateway (`docker compose exec mirror-gateway nginx -s reload`). +- **Quota tuning** – adjust per-domain `MAXDOWNLOADREQUESTSPERHOUR` in `.env` or values file. + Align CDN rate limits and inform downstreams. + +## 8. References + +- Deployment profiles: `deploy/compose/docker-compose.mirror.yaml`, + `deploy/helm/stellaops/values-mirror.yaml` +- Mirror architecture dossiers: `docs/modules/concelier/architecture.md`, + `docs/modules/excititor/mirrors.md` +- Export bundling: `docs/modules/devops/architecture.md` §3, `docs/modules/excititor/architecture.md` §7 diff --git a/docs/modules/devops/AGENTS.md b/docs/modules/devops/AGENTS.md new file mode 100644 index 00000000..e244ae19 --- /dev/null +++ b/docs/modules/devops/AGENTS.md @@ -0,0 +1,22 @@ +# DevOps agent guide + +## Mission +The DevOps module captures release, deployment, and migration playbooks that keep StellaOps deterministic across environments. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/devops/README.md b/docs/modules/devops/README.md new file mode 100644 index 00000000..2363ec64 --- /dev/null +++ b/docs/modules/devops/README.md @@ -0,0 +1,41 @@ +# StellaOps DevOps + +The DevOps module captures release, deployment, and migration playbooks that keep StellaOps deterministic across environments. + +## Responsibilities +- Maintain CI pipelines, signing workflows, and release packaging steps. +- Operate shared runbooks for launch readiness, upgrades, and NuGet previews. +- Provide offline kit assembly instructions and tooling integration. +- Wrap observability/telemetry bootstrap flows for platform teams. + +## Key components +- Runbooks under ./runbooks/ (launch, deployment, nuget). +- Migration guidance under ./migrations/. +- Architecture overview bridging CI/CD & infrastructure concerns. + +## Integrations & dependencies +- Ops pipelines (Gitea, GitHub Actions) and artifact registries. +- Authority/Signer for supply chain signing. +- Telemetry stack bootstrap scripts. + +## Operational notes +- Offline bundle packaging guidance in docs/modules/export-center/operations/runbook.md. +- Dashboards for launch cutover rehearsals. +- Coordination with Security for enforced guardrails. + +## Related resources +- ./runbooks/launch-readiness.md +- ./runbooks/launch-cutover.md +- ./runbooks/deployment-upgrade.md +- ./runbooks/nuget-preview-bootstrap.md +- ./migrations/semver-style.md + +## Backlog references +- DEVOPS-LAUNCH-18-001 / 18-900 runbooks in ../../TASKS.md. +- Telemetry bootstrap automation tracked in `ops/devops/TASKS.md`. + +## Epic alignment +- **Epic 1 – AOC enforcement:** bake AOC verifier steps, CI guards, and schema validation into pipelines. +- **Epic 9 – Orchestrator Dashboard:** support operational dashboards, job recovery runbooks, and rate-limit governance. +- **Epic 10 – Export Center:** manage signing workflows, Offline Kit packaging, and release promotion for exports. +- **Epic 15 – Observability & Forensics:** coordinate telemetry deployment, evidence retention, and forensic automation. diff --git a/docs/modules/devops/TASKS.md b/docs/modules/devops/TASKS.md new file mode 100644 index 00000000..92ad1da0 --- /dev/null +++ b/docs/modules/devops/TASKS.md @@ -0,0 +1,9 @@ +# Task board — DevOps + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| DEVOPS-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| DEVOPS-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| DEVOPS-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_DEVOPS.md b/docs/modules/devops/architecture.md similarity index 95% rename from docs/ARCHITECTURE_DEVOPS.md rename to docs/modules/devops/architecture.md index 2eb884a1..815cd4ab 100644 --- a/docs/ARCHITECTURE_DEVOPS.md +++ b/docs/modules/devops/architecture.md @@ -1,5 +1,7 @@ # component_architecture_devops.md — **Stella Ops Release & Operations** (2025Q4) +> Draws from the AOC guardrails, Orchestrator, Export Center, and Observability module plans to describe how Stella Ops is built, signed, distributed, and operated. + > **Scope.** Implementation‑ready blueprint for **how Stella Ops is built, versioned, signed, distributed, upgraded, licensed (PoE)**, and operated in customer environments (online and air‑gapped). Covers reproducible builds, supply‑chain attestations, registries, offline kits, migration/rollback, artifact lifecycle (RustFS default + Mongo, S3 fallback), monitoring SLOs, and customer activation. --- @@ -76,7 +78,7 @@ At startup, services **self‑advertise** their semver & channel; the UI surface * **Unit/integration**: per‑component, plus **end‑to‑end** flows (scan→vex→policy→sign→attest). * **Perf SLOs**: hot paths (SBOM compose, diff, export) measured against budgets. * **Security**: dependency audit vs Concelier export; container hardening tests; minimal caps. -* **Analyzer smoke**: restart-time language plug-ins (currently Python) verified via `dotnet run --project tools/LanguageAnalyzerSmoke` to ensure manifest integrity plus cold vs warm determinism (< 30 s / < 5 s budgets); the harness logs deviations from repository goldens for follow-up. +* **Analyzer smoke**: restart-time language plug-ins (currently Python) verified via `dotnet run --project src/Tools/LanguageAnalyzerSmoke` to ensure manifest integrity plus cold vs warm determinism (< 30 s / < 5 s budgets); the harness logs deviations from repository goldens for follow-up. * **Canary cohort**: internal staging + selected customers; one week on **edge** before **stable** tag. ### 2.5 Debug-store artefacts @@ -92,7 +94,7 @@ At startup, services **self‑advertise** their semver & channel; the UI surface * **Primary**: `registry.stella-ops.org` (OCI v2, supports Referrers API). * **Mirrors**: GHCR (read‑only), regional mirrors for latency. - * Operational runbook: see `docs/ops/concelier-mirror-operations.md` for deployment profiles, CDN guidance, and sync automation. + * Operational runbook: see `docs/modules/concelier/operations/mirror.md` for deployment profiles, CDN guidance, and sync automation. * **Pull by digest only** in Kubernetes/Compose manifests. **Gating policy**: @@ -111,7 +113,7 @@ At startup, services **self‑advertise** their semver & channel; the UI surface 3. Registry allows pull for the requested repo. * Tokens are **short‑lived** (60–300 s) and **DPoP‑bound**. -The token service enforces plan gating via `registry-token.yaml` (see `docs/ops/registry-token-service.md`) and exposes Prometheus metrics (`registry_token_issued_total`, `registry_token_rejected_total`). Revoked licence identifiers halt issuance even when scope requirements are met. +The token service enforces plan gating via `registry-token.yaml` (see `docs/modules/registry/operations/token-service.md`) and exposes Prometheus metrics (`registry_token_issued_total`, `registry_token_rejected_total`). Revoked licence identifiers halt issuance even when scope requirements are met. ### 3.3 Offline kits (air‑gapped) @@ -300,7 +302,7 @@ rustfs://stellaops/ * Artifacts referenced by **reports** or **tickets** are pinned. * ILM actions logged; UI shows per‑class usage & upcoming purges. -> **Migration note.** Follow `docs/ops/scanner-rustfs-migration.md` when transitioning existing +> **Migration note.** Follow `docs/modules/scanner/operations/rustfs-migration.md` when transitioning existing > MinIO buckets to RustFS. The provided migrator is idempotent and safe to rerun per prefix. ### 7.4 Mongo retention diff --git a/docs/modules/devops/implementation_plan.md b/docs/modules/devops/implementation_plan.md new file mode 100644 index 00000000..005a9577 --- /dev/null +++ b/docs/modules/devops/implementation_plan.md @@ -0,0 +1,22 @@ +# Implementation plan — DevOps + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 1 – AOC enforcement:** ensure CI/CD guardrails, schema validation, and verifier pipelines are enforced. +- **Epic 9 – Orchestrator Dashboard:** deliver dashboards, recovery runbooks, and rate-limit governance. +- **Epic 10 – Export Center:** manage signing/promotions and Offline Kit bundle publishing. +- **Epic 15 – Observability & Forensics:** coordinate telemetry deployments, evidence retention, and forensic automation. +- Track module runbooks (DEVOPS-LAUNCH-18-001/900) and telemetry automation via ../../TASKS.md and ops/devops/TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ops/migrations/SEMVER_STYLE.md b/docs/modules/devops/migrations/semver-style.md similarity index 100% rename from docs/ops/migrations/SEMVER_STYLE.md rename to docs/modules/devops/migrations/semver-style.md diff --git a/docs/ops/deployment-upgrade-runbook.md b/docs/modules/devops/runbooks/deployment-upgrade.md similarity index 93% rename from docs/ops/deployment-upgrade-runbook.md rename to docs/modules/devops/runbooks/deployment-upgrade.md index ba4a3421..af72f3d2 100644 --- a/docs/ops/deployment-upgrade-runbook.md +++ b/docs/modules/devops/runbooks/deployment-upgrade.md @@ -1,151 +1,151 @@ -# Stella Ops Deployment Upgrade & Rollback Runbook - -_Last updated: 2025-10-26 (Sprint 14 – DEVOPS-OPS-14-003)._ - -This runbook describes how to promote a new release across the supported deployment profiles (Helm and Docker Compose), how to roll back safely, and how to keep channels (`edge`, `stable`, `airgap`) aligned. All steps assume you are working from a clean checkout of the release branch/tag. - ---- - -## 1. Channel overview - -| Channel | Release manifest | Helm values | Compose profile | -|---------|------------------|-------------|-----------------| -| `edge` | `deploy/releases/2025.10-edge.yaml` | `deploy/helm/stellaops/values-dev.yaml` | `deploy/compose/docker-compose.dev.yaml` | -| `stable` | `deploy/releases/2025.09-stable.yaml` | `deploy/helm/stellaops/values-stage.yaml`, `deploy/helm/stellaops/values-prod.yaml` | `deploy/compose/docker-compose.stage.yaml`, `deploy/compose/docker-compose.prod.yaml` | -| `airgap` | `deploy/releases/2025.09-airgap.yaml` | `deploy/helm/stellaops/values-airgap.yaml` | `deploy/compose/docker-compose.airgap.yaml` | - -Infrastructure components (MongoDB, MinIO, RustFS) are pinned in the release manifests and inherited by the deployment profiles. Supporting dependencies such as `nats` remain on upstream LTS tags; review `deploy/compose/*.yaml` for the authoritative set. - ---- - -## 2. Pre-flight checklist - -1. **Refresh release manifest** - Pull the latest manifest for the channel you are promoting (`deploy/releases/-.yaml`). - -2. **Align deployment bundles with the manifest** - Run the alignment checker for every profile that should pick up the release. Pass `--ignore-repo nats` to skip auxiliary services. - ```bash - ./deploy/tools/check-channel-alignment.py \ - --release deploy/releases/2025.10-edge.yaml \ - --target deploy/helm/stellaops/values-dev.yaml \ - --target deploy/compose/docker-compose.dev.yaml \ - --ignore-repo nats - ``` - Repeat for other channels (`stable`, `airgap`), substituting the manifest and target files. - -3. **Lint and template profiles** - ```bash - ./deploy/tools/validate-profiles.sh - ``` - -4. **Smoke the Offline Kit debug store (edge/stable only)** - When the release pipeline has generated `out/release/debug/.build-id/**`, mirror the assets into the Offline Kit staging tree: - ```bash - ./ops/offline-kit/mirror_debug_store.py \ - --release-dir out/release \ - --offline-kit-dir out/offline-kit - ``` - Archive the resulting `out/offline-kit/metadata/debug-store.json` alongside the kit bundle. - -5. **Review compatibility matrix** - Confirm MongoDB, MinIO, and RustFS versions in the release manifest match platform SLOs. The default targets are `mongo@sha256:c258…`, `minio@sha256:14ce…`, `rustfs:2025.10.0-edge`. - -6. **Create a rollback bookmark** - Record the current Helm revision (`helm history stellaops -n stellaops`) and compose tag (`git describe --tags`) before applying changes. - ---- - -## 3. Helm upgrade procedure (staging → production) - -1. Switch to the deployment branch and ensure secrets/config maps are current. -2. Apply the upgrade in the staging cluster: - ```bash - helm upgrade stellaops deploy/helm/stellaops \ - -f deploy/helm/stellaops/values-stage.yaml \ - --namespace stellaops \ - --atomic \ - --timeout 15m - ``` -3. Run smoke tests (`scripts/smoke-tests.sh` or environment-specific checks). -4. Promote to production using the prod values file and the same command. -5. Record the new revision number and Git SHA in the change log. - -### Rollback (Helm) - -1. Identify the previous revision: `helm history stellaops -n stellaops`. -2. Execute: - ```bash - helm rollback stellaops \ - --namespace stellaops \ - --wait \ - --timeout 10m - ``` -3. Verify `kubectl get pods` returns healthy workloads; rerun smoke tests. -4. Update the incident/operations log with root cause and rollback details. - ---- - -## 4. Docker Compose upgrade procedure - -1. Update environment files (`deploy/compose/env/*.env.example`) with any new settings and sync secrets to hosts. -2. Pull the tagged repository state corresponding to the release (e.g. `git checkout 2025.09.2` for stable). -3. Apply the upgrade: - ```bash - docker compose \ - --env-file deploy/compose/env/prod.env \ - -f deploy/compose/docker-compose.prod.yaml \ - pull - - docker compose \ - --env-file deploy/compose/env/prod.env \ - -f deploy/compose/docker-compose.prod.yaml \ - up -d - ``` -4. Tail logs for critical services (`docker compose logs -f authority concelier`). -5. Update monitoring dashboards/alerts to confirm normal operation. - -### Rollback (Compose) - -1. Check out the previous release tag (e.g. `git checkout 2025.09.1`). -2. Re-run `docker compose pull` and `docker compose up -d` with that profile. Docker will restore the prior digests. -3. If reverting to a known-good snapshot is required, restore volume backups (see `docs/ops/authority-backup-restore.md` and associated service guides). -4. Log the rollback in the operations journal. - ---- - -## 5. Channel promotion workflow - -1. Author or update the channel manifest under `deploy/releases/`. -2. Mirror the new digests into Helm/Compose values and run the alignment script for each profile. -3. Commit the changes with a message that references the release version and channel (e.g. `deploy: promote 2025.10.0-edge`). -4. Publish release notes and update `deploy/releases/README.md` (if applicable). -5. Tag the repository when promoting stable or airgap builds. - ---- - -## 6. Upgrade rehearsal & rollback drill log - -Maintain rehearsal notes in `docs/ops/launch-cutover.md` or the relevant sprint planning document. After each drill capture: - -- Release version tested -- Date/time -- Participants -- Issues encountered & fixes -- Rollback duration (if executed) - -Attach the log to the sprint retro or operational wiki. - -| Date (UTC) | Channel | Outcome | Notes | -|------------|---------|---------|-------| -| 2025-10-26 | Documentation dry-run | Planned | Runbook refreshed; next live drill scheduled for 2025-11 edge → stable promotion. - ---- - -## 7. References - -- `deploy/README.md` – structure and validation workflow for deployment bundles. -- `docs/13_RELEASE_ENGINEERING_PLAYBOOK.md` – release automation and signing pipeline. -- `docs/ARCHITECTURE_DEVOPS.md` – high-level DevOps architecture, SLOs, and compliance requirements. -- `ops/offline-kit/mirror_debug_store.py` – debug-store mirroring helper. -- `deploy/tools/check-channel-alignment.py` – release vs deployment digest alignment checker. +# Stella Ops Deployment Upgrade & Rollback Runbook + +_Last updated: 2025-10-26 (Sprint 14 – DEVOPS-OPS-14-003)._ + +This runbook describes how to promote a new release across the supported deployment profiles (Helm and Docker Compose), how to roll back safely, and how to keep channels (`edge`, `stable`, `airgap`) aligned. All steps assume you are working from a clean checkout of the release branch/tag. + +--- + +## 1. Channel overview + +| Channel | Release manifest | Helm values | Compose profile | +|---------|------------------|-------------|-----------------| +| `edge` | `deploy/releases/2025.10-edge.yaml` | `deploy/helm/stellaops/values-dev.yaml` | `deploy/compose/docker-compose.dev.yaml` | +| `stable` | `deploy/releases/2025.09-stable.yaml` | `deploy/helm/stellaops/values-stage.yaml`, `deploy/helm/stellaops/values-prod.yaml` | `deploy/compose/docker-compose.stage.yaml`, `deploy/compose/docker-compose.prod.yaml` | +| `airgap` | `deploy/releases/2025.09-airgap.yaml` | `deploy/helm/stellaops/values-airgap.yaml` | `deploy/compose/docker-compose.airgap.yaml` | + +Infrastructure components (MongoDB, MinIO, RustFS) are pinned in the release manifests and inherited by the deployment profiles. Supporting dependencies such as `nats` remain on upstream LTS tags; review `deploy/compose/*.yaml` for the authoritative set. + +--- + +## 2. Pre-flight checklist + +1. **Refresh release manifest** + Pull the latest manifest for the channel you are promoting (`deploy/releases/-.yaml`). + +2. **Align deployment bundles with the manifest** + Run the alignment checker for every profile that should pick up the release. Pass `--ignore-repo nats` to skip auxiliary services. + ```bash + ./deploy/tools/check-channel-alignment.py \ + --release deploy/releases/2025.10-edge.yaml \ + --target deploy/helm/stellaops/values-dev.yaml \ + --target deploy/compose/docker-compose.dev.yaml \ + --ignore-repo nats + ``` + Repeat for other channels (`stable`, `airgap`), substituting the manifest and target files. + +3. **Lint and template profiles** + ```bash + ./deploy/tools/validate-profiles.sh + ``` + +4. **Smoke the Offline Kit debug store (edge/stable only)** + When the release pipeline has generated `out/release/debug/.build-id/**`, mirror the assets into the Offline Kit staging tree: + ```bash + ./ops/offline-kit/mirror_debug_store.py \ + --release-dir out/release \ + --offline-kit-dir out/offline-kit + ``` + Archive the resulting `out/offline-kit/metadata/debug-store.json` alongside the kit bundle. + +5. **Review compatibility matrix** + Confirm MongoDB, MinIO, and RustFS versions in the release manifest match platform SLOs. The default targets are `mongo@sha256:c258…`, `minio@sha256:14ce…`, `rustfs:2025.10.0-edge`. + +6. **Create a rollback bookmark** + Record the current Helm revision (`helm history stellaops -n stellaops`) and compose tag (`git describe --tags`) before applying changes. + +--- + +## 3. Helm upgrade procedure (staging → production) + +1. Switch to the deployment branch and ensure secrets/config maps are current. +2. Apply the upgrade in the staging cluster: + ```bash + helm upgrade stellaops deploy/helm/stellaops \ + -f deploy/helm/stellaops/values-stage.yaml \ + --namespace stellaops \ + --atomic \ + --timeout 15m + ``` +3. Run smoke tests (`scripts/smoke-tests.sh` or environment-specific checks). +4. Promote to production using the prod values file and the same command. +5. Record the new revision number and Git SHA in the change log. + +### Rollback (Helm) + +1. Identify the previous revision: `helm history stellaops -n stellaops`. +2. Execute: + ```bash + helm rollback stellaops \ + --namespace stellaops \ + --wait \ + --timeout 10m + ``` +3. Verify `kubectl get pods` returns healthy workloads; rerun smoke tests. +4. Update the incident/operations log with root cause and rollback details. + +--- + +## 4. Docker Compose upgrade procedure + +1. Update environment files (`deploy/compose/env/*.env.example`) with any new settings and sync secrets to hosts. +2. Pull the tagged repository state corresponding to the release (e.g. `git checkout 2025.09.2` for stable). +3. Apply the upgrade: + ```bash + docker compose \ + --env-file deploy/compose/env/prod.env \ + -f deploy/compose/docker-compose.prod.yaml \ + pull + + docker compose \ + --env-file deploy/compose/env/prod.env \ + -f deploy/compose/docker-compose.prod.yaml \ + up -d + ``` +4. Tail logs for critical services (`docker compose logs -f authority concelier`). +5. Update monitoring dashboards/alerts to confirm normal operation. + +### Rollback (Compose) + +1. Check out the previous release tag (e.g. `git checkout 2025.09.1`). +2. Re-run `docker compose pull` and `docker compose up -d` with that profile. Docker will restore the prior digests. +3. If reverting to a known-good snapshot is required, restore volume backups (see `docs/modules/authority/operations/backup-restore.md` and associated service guides). +4. Log the rollback in the operations journal. + +--- + +## 5. Channel promotion workflow + +1. Author or update the channel manifest under `deploy/releases/`. +2. Mirror the new digests into Helm/Compose values and run the alignment script for each profile. +3. Commit the changes with a message that references the release version and channel (e.g. `deploy: promote 2025.10.0-edge`). +4. Publish release notes and update `deploy/releases/README.md` (if applicable). +5. Tag the repository when promoting stable or airgap builds. + +--- + +## 6. Upgrade rehearsal & rollback drill log + +Maintain rehearsal notes in `docs/modules/devops/runbooks/launch-cutover.md` or the relevant sprint planning document. After each drill capture: + +- Release version tested +- Date/time +- Participants +- Issues encountered & fixes +- Rollback duration (if executed) + +Attach the log to the sprint retro or operational wiki. + +| Date (UTC) | Channel | Outcome | Notes | +|------------|---------|---------|-------| +| 2025-10-26 | Documentation dry-run | Planned | Runbook refreshed; next live drill scheduled for 2025-11 edge → stable promotion. + +--- + +## 7. References + +- `deploy/README.md` – structure and validation workflow for deployment bundles. +- `docs/13_RELEASE_ENGINEERING_PLAYBOOK.md` – release automation and signing pipeline. +- `docs/modules/devops/architecture.md` – high-level DevOps architecture, SLOs, and compliance requirements. +- `ops/offline-kit/mirror_debug_store.py` – debug-store mirroring helper. +- `deploy/tools/check-channel-alignment.py` – release vs deployment digest alignment checker. diff --git a/docs/ops/launch-cutover.md b/docs/modules/devops/runbooks/launch-cutover.md similarity index 97% rename from docs/ops/launch-cutover.md rename to docs/modules/devops/runbooks/launch-cutover.md index cf9c5c05..c35d5a2e 100644 --- a/docs/ops/launch-cutover.md +++ b/docs/modules/devops/runbooks/launch-cutover.md @@ -1,128 +1,128 @@ -# Launch Cutover Runbook - Stella Ops - -_Document owner: DevOps Guild (2025-10-26)_ -_Scope:_ Full-platform launch from staging to production for release `2025.09.2`. - -## 1. Roles and Communication - -| Role | Primary | Backup | Contact | -| --- | --- | --- | --- | -| Cutover lead | DevOps Guild (on-call engineer) | Platform Ops lead | `#launch-bridge` (Mattermost) | -| Authority stack | Authority Core guild rep | Security guild rep | `#authority` | -| Scanner / Queue | Scanner WebService guild rep | Runtime guild rep | `#scanner` | -| Storage | Mongo/MinIO operators | Backup DB admin | Pager escalation | -| Observability | Telemetry guild rep | SRE on-call | `#telemetry` | -| Approvals | Product owner + CTO | DevOps lead | Approval recorded in change ticket | - -Set up a bridge call 30 minutes before start and keep `#launch-bridge` updated every 10 minutes. - -## 2. Timeline Overview (UTC) - -| Time | Activity | Owner | -| --- | --- | --- | -| T-24h | Change ticket approved, prod secrets verified, offline kit build status checked (`DEVOPS-OFFLINE-18-005`). | DevOps lead | -| T-12h | Run `deploy/tools/validate-profiles.sh`; capture logs in ticket. | DevOps engineer | -| T-6h | Freeze non-launch deployments; notify guild leads. | Product owner | -| T-2h | Execute rehearsal in staging (Section 3) using `values-stage.yaml` to verify scripts. | DevOps + module reps | -| T-30m | Final go/no-go with guild leads; confirm monitoring dashboards green. | Cutover lead | -| T0 | Execute production cutover steps (Section 4). | Cutover team | -| T+45m | Smoke tests complete (Section 5); announce success or trigger rollback. | Cutover lead | -| T+4h | Post-cutover metrics review, notify stakeholders, close ticket. | DevOps + product owner | - -## 3. Rehearsal (Staging) Checklist - -1. `docker network create stellaops_frontdoor || true` (if not present on staging jump host). -2. Run `deploy/tools/validate-profiles.sh` and archive output. -3. Apply staging secrets (`kubectl apply -f secrets/stage/*.yaml` or `helm secrets upgrade`) ensuring `stellaops-stage` credentials align with `values-stage.yaml`. -4. Perform `helm upgrade stellaops deploy/helm/stellaops -f deploy/helm/stellaops/values-stage.yaml` in staging cluster. -5. Verify health endpoints: `curl https://authority.stage.../healthz`, `curl https://scanner.stage.../healthz`. -6. Execute smoke CLI: `stellaops-cli scan submit --profile staging --sbom samples/sbom/demo.json` and confirm report status in UI. -7. Document total wall time and any deviations in the rehearsal log. - -Rehearsal must complete without manual interventions before proceeding to production. - -## 4. Production Cutover Steps - -### 4.1 Pre-flight -- Confirm production secrets in the appropriate secret store (`stellaops-prod-core`, `stellaops-prod-mongo`, `stellaops-prod-minio`, `stellaops-prod-notify`) contain the keys referenced in `values-prod.yaml`. -- Ensure the external reverse proxy network exists: `docker network create stellaops_frontdoor || true` on each compose host. -- Back up current configuration and data: - - Mongo snapshot: `mongodump --uri "$MONGO_BACKUP_URI" --out /backups/launch-$(date -Iseconds)`. - - MinIO policy export: `mc mirror --overwrite minio/stellaops minio-backup/stellaops-$(date +%Y%m%d%H%M)`. - -### 4.2 Apply Updates (Compose) -1. On each compose node, pull updated images for release `2025.09.2`: - ```bash - docker compose --env-file prod.env -f deploy/compose/docker-compose.prod.yaml pull - ``` -2. Deploy changes: - ```bash - docker compose --env-file prod.env -f deploy/compose/docker-compose.prod.yaml up -d - ``` -3. Confirm containers healthy via `docker compose ps` and `docker logs --tail 50`. - -### 4.3 Apply Updates (Helm/Kubernetes) -If using Kubernetes, perform: -```bash -helm upgrade stellaops deploy/helm/stellaops -f deploy/helm/stellaops/values-prod.yaml --atomic --timeout 15m -``` -Monitor rollout with `kubectl get pods -n stellaops --watch` and `kubectl rollout status deployment/`. - -### 4.4 Configuration Validation -- Verify Authority issuer metadata: `curl https://authority.prod.../.well-known/openid-configuration`. -- Validate Signer DSSE endpoint: `stellaops-cli signer verify --base-url https://signer.prod... --bundle samples/dsse/demo.json`. -- Check Scanner queue connectivity: `docker exec stellaops-scanner-web dotnet StellaOps.Scanner.WebService.dll health queue` (returns success). -- Ensure Notify (legacy) still accessible while Notifier migration pending. - -## 5. Smoke Tests - -| Test | Command / Action | Expected Result | -| --- | --- | --- | -| API health | `curl https://scanner.prod.../healthz` | HTTP 200 with `status":"Healthy"` | -| Scan submit | `stellaops-cli scan submit --profile prod --sbom samples/sbom/demo.json` | Scan completes < 5 minutes; report accessible with signed DSSE | -| Runtime event ingest | Post sample event from Zastava observer fixture | `/runtime/events` responds 202 Accepted; record visible in Mongo `runtime_events` | -| Signing | `stellaops-cli signer sign --bundle demo.json` | Returns DSSE with matching SHA256 and signer metadata | -| Attestor verify | `stellaops-cli attestor verify --uuid ` | Verification result `ok=true` | -| Web UI | Manual login, verify dashboards render and latency within budget | UI loads under 2 seconds; policy views consistent | - -Log results in the change ticket with timestamps and screenshots where applicable. - -## 6. Rollback Procedure - -1. Assess failure scope; if systemic, initiate rollback immediately while preserving logs/artifacts. -2. For Compose: - ```bash - docker compose --env-file prod.env -f deploy/compose/docker-compose.prod.yaml down - docker compose --env-file stage.env -f deploy/compose/docker-compose.stage.yaml up -d - ``` -3. For Helm: - ```bash - helm rollback stellaops --namespace stellaops - ``` -4. Restore Mongo snapshot if data inconsistency detected: `mongorestore --uri "$MONGO_BACKUP_URI" --drop /backups/launch-`. -5. Restore MinIO mirror if required: `mc mirror minio-backup/stellaops- minio/stellaops`. -6. Notify stakeholders of rollback and capture root cause notes in incident ticket. - -## 7. Post-cutover Actions - -- Keep heightened monitoring for 4 hours post cutover; track latency, error rates, and queue depth. -- Confirm audit trails: Authority tokens issued, Scanner events recorded, Attestor submissions stored. -- Update `docs/ops/launch-readiness.md` if any new gaps or follow-ups discovered. -- Schedule retrospective within 48 hours; include DevOps, module guilds, and product owner. - -## 8. Approval Matrix - -| Step | Required Approvers | Record Location | -| --- | --- | --- | -| Production deployment plan | CTO + DevOps lead | Change ticket comment | -| Cutover start (T0) | DevOps lead + module reps | `#launch-bridge` summary | -| Post-smoke success | DevOps lead + product owner | Change ticket closure | -| Rollback (if invoked) | DevOps lead + CTO | Incident ticket | - -Retain all approvals and logs for audit. Update this runbook after each execution to record actual timings and lessons learned. - -## 9. Rehearsal Log - -| Date (UTC) | What We Exercised | Outcome | Follow-up | -| --- | --- | --- | --- | -| 2025-10-26 | Dry-run of compose/Helm validation via `deploy/tools/validate-profiles.sh` (dev/stage/prod/airgap/mirror). Network creation simulated (`docker network create stellaops_frontdoor` planned) and stage CLI submission reviewed. | Validation script succeeded; all profiles templated cleanly. Stage deployment apply deferred because no staging cluster is accessible from the current environment. | Schedule full stage rehearsal once staging cluster credentials are available; reuse this log section to capture timings. | +# Launch Cutover Runbook - Stella Ops + +_Document owner: DevOps Guild (2025-10-26)_ +_Scope:_ Full-platform launch from staging to production for release `2025.09.2`. + +## 1. Roles and Communication + +| Role | Primary | Backup | Contact | +| --- | --- | --- | --- | +| Cutover lead | DevOps Guild (on-call engineer) | Platform Ops lead | `#launch-bridge` (Mattermost) | +| Authority stack | Authority Core guild rep | Security guild rep | `#authority` | +| Scanner / Queue | Scanner WebService guild rep | Runtime guild rep | `#scanner` | +| Storage | Mongo/MinIO operators | Backup DB admin | Pager escalation | +| Observability | Telemetry guild rep | SRE on-call | `#telemetry` | +| Approvals | Product owner + CTO | DevOps lead | Approval recorded in change ticket | + +Set up a bridge call 30 minutes before start and keep `#launch-bridge` updated every 10 minutes. + +## 2. Timeline Overview (UTC) + +| Time | Activity | Owner | +| --- | --- | --- | +| T-24h | Change ticket approved, prod secrets verified, offline kit build status checked (`DEVOPS-OFFLINE-18-005`). | DevOps lead | +| T-12h | Run `deploy/tools/validate-profiles.sh`; capture logs in ticket. | DevOps engineer | +| T-6h | Freeze non-launch deployments; notify guild leads. | Product owner | +| T-2h | Execute rehearsal in staging (Section 3) using `values-stage.yaml` to verify scripts. | DevOps + module reps | +| T-30m | Final go/no-go with guild leads; confirm monitoring dashboards green. | Cutover lead | +| T0 | Execute production cutover steps (Section 4). | Cutover team | +| T+45m | Smoke tests complete (Section 5); announce success or trigger rollback. | Cutover lead | +| T+4h | Post-cutover metrics review, notify stakeholders, close ticket. | DevOps + product owner | + +## 3. Rehearsal (Staging) Checklist + +1. `docker network create stellaops_frontdoor || true` (if not present on staging jump host). +2. Run `deploy/tools/validate-profiles.sh` and archive output. +3. Apply staging secrets (`kubectl apply -f secrets/stage/*.yaml` or `helm secrets upgrade`) ensuring `stellaops-stage` credentials align with `values-stage.yaml`. +4. Perform `helm upgrade stellaops deploy/helm/stellaops -f deploy/helm/stellaops/values-stage.yaml` in staging cluster. +5. Verify health endpoints: `curl https://authority.stage.../healthz`, `curl https://scanner.stage.../healthz`. +6. Execute smoke CLI: `stellaops-cli scan submit --profile staging --sbom samples/sbom/demo.json` and confirm report status in UI. +7. Document total wall time and any deviations in the rehearsal log. + +Rehearsal must complete without manual interventions before proceeding to production. + +## 4. Production Cutover Steps + +### 4.1 Pre-flight +- Confirm production secrets in the appropriate secret store (`stellaops-prod-core`, `stellaops-prod-mongo`, `stellaops-prod-minio`, `stellaops-prod-notify`) contain the keys referenced in `values-prod.yaml`. +- Ensure the external reverse proxy network exists: `docker network create stellaops_frontdoor || true` on each compose host. +- Back up current configuration and data: + - Mongo snapshot: `mongodump --uri "$MONGO_BACKUP_URI" --out /backups/launch-$(date -Iseconds)`. + - MinIO policy export: `mc mirror --overwrite minio/stellaops minio-backup/stellaops-$(date +%Y%m%d%H%M)`. + +### 4.2 Apply Updates (Compose) +1. On each compose node, pull updated images for release `2025.09.2`: + ```bash + docker compose --env-file prod.env -f deploy/compose/docker-compose.prod.yaml pull + ``` +2. Deploy changes: + ```bash + docker compose --env-file prod.env -f deploy/compose/docker-compose.prod.yaml up -d + ``` +3. Confirm containers healthy via `docker compose ps` and `docker logs --tail 50`. + +### 4.3 Apply Updates (Helm/Kubernetes) +If using Kubernetes, perform: +```bash +helm upgrade stellaops deploy/helm/stellaops -f deploy/helm/stellaops/values-prod.yaml --atomic --timeout 15m +``` +Monitor rollout with `kubectl get pods -n stellaops --watch` and `kubectl rollout status deployment/`. + +### 4.4 Configuration Validation +- Verify Authority issuer metadata: `curl https://authority.prod.../.well-known/openid-configuration`. +- Validate Signer DSSE endpoint: `stellaops-cli signer verify --base-url https://signer.prod... --bundle samples/dsse/demo.json`. +- Check Scanner queue connectivity: `docker exec stellaops-scanner-web dotnet StellaOps.Scanner.WebService.dll health queue` (returns success). +- Ensure Notify (legacy) still accessible while Notifier migration pending. + +## 5. Smoke Tests + +| Test | Command / Action | Expected Result | +| --- | --- | --- | +| API health | `curl https://scanner.prod.../healthz` | HTTP 200 with `status":"Healthy"` | +| Scan submit | `stellaops-cli scan submit --profile prod --sbom samples/sbom/demo.json` | Scan completes < 5 minutes; report accessible with signed DSSE | +| Runtime event ingest | Post sample event from Zastava observer fixture | `/runtime/events` responds 202 Accepted; record visible in Mongo `runtime_events` | +| Signing | `stellaops-cli signer sign --bundle demo.json` | Returns DSSE with matching SHA256 and signer metadata | +| Attestor verify | `stellaops-cli attestor verify --uuid ` | Verification result `ok=true` | +| Web UI | Manual login, verify dashboards render and latency within budget | UI loads under 2 seconds; policy views consistent | + +Log results in the change ticket with timestamps and screenshots where applicable. + +## 6. Rollback Procedure + +1. Assess failure scope; if systemic, initiate rollback immediately while preserving logs/artifacts. +2. For Compose: + ```bash + docker compose --env-file prod.env -f deploy/compose/docker-compose.prod.yaml down + docker compose --env-file stage.env -f deploy/compose/docker-compose.stage.yaml up -d + ``` +3. For Helm: + ```bash + helm rollback stellaops --namespace stellaops + ``` +4. Restore Mongo snapshot if data inconsistency detected: `mongorestore --uri "$MONGO_BACKUP_URI" --drop /backups/launch-`. +5. Restore MinIO mirror if required: `mc mirror minio-backup/stellaops- minio/stellaops`. +6. Notify stakeholders of rollback and capture root cause notes in incident ticket. + +## 7. Post-cutover Actions + +- Keep heightened monitoring for 4 hours post cutover; track latency, error rates, and queue depth. +- Confirm audit trails: Authority tokens issued, Scanner events recorded, Attestor submissions stored. +- Update `docs/modules/devops/runbooks/launch-readiness.md` if any new gaps or follow-ups discovered. +- Schedule retrospective within 48 hours; include DevOps, module guilds, and product owner. + +## 8. Approval Matrix + +| Step | Required Approvers | Record Location | +| --- | --- | --- | +| Production deployment plan | CTO + DevOps lead | Change ticket comment | +| Cutover start (T0) | DevOps lead + module reps | `#launch-bridge` summary | +| Post-smoke success | DevOps lead + product owner | Change ticket closure | +| Rollback (if invoked) | DevOps lead + CTO | Incident ticket | + +Retain all approvals and logs for audit. Update this runbook after each execution to record actual timings and lessons learned. + +## 9. Rehearsal Log + +| Date (UTC) | What We Exercised | Outcome | Follow-up | +| --- | --- | --- | --- | +| 2025-10-26 | Dry-run of compose/Helm validation via `deploy/tools/validate-profiles.sh` (dev/stage/prod/airgap/mirror). Network creation simulated (`docker network create stellaops_frontdoor` planned) and stage CLI submission reviewed. | Validation script succeeded; all profiles templated cleanly. Stage deployment apply deferred because no staging cluster is accessible from the current environment. | Schedule full stage rehearsal once staging cluster credentials are available; reuse this log section to capture timings. | diff --git a/docs/ops/launch-readiness.md b/docs/modules/devops/runbooks/launch-readiness.md similarity index 95% rename from docs/ops/launch-readiness.md rename to docs/modules/devops/runbooks/launch-readiness.md index 8dab5aeb..cf20d289 100644 --- a/docs/ops/launch-readiness.md +++ b/docs/modules/devops/runbooks/launch-readiness.md @@ -1,49 +1,49 @@ -# Launch Readiness Record - Stella Ops - -_Updated: 2025-10-26 (UTC)_ - -This document captures production launch sign-offs, deployment readiness checkpoints, and any open risks that must be tracked before GA cutover. - -## 1. Sign-off Summary - -| Module / Service | Guild / Point of Contact | Evidence (Task or Runbook) | Status | Timestamp (UTC) | Notes | -| --- | --- | --- | --- | --- | --- | -| Authority (Issuer) | Authority Core Guild | `AUTH-AOC-19-001` - scope issuance & configuration complete (DONE 2025-10-26) | READY | 2025-10-26T14:05Z | Tenant scope propagation follow-up (`AUTH-AOC-19-002`) tracked in gaps section. | -| Signer | Signer Guild | `SIGNER-API-11-101` / `SIGNER-REF-11-102` / `SIGNER-QUOTA-11-103` (DONE 2025-10-21) | READY | 2025-10-26T14:07Z | DSSE signing, referrer verification, and quota enforcement validated in CI. | -| Attestor | Attestor Guild | `ATTESTOR-API-11-201` / `ATTESTOR-VERIFY-11-202` / `ATTESTOR-OBS-11-203` (DONE 2025-10-19) | READY | 2025-10-26T14:10Z | Rekor submission/verification pipeline green; telemetry pack published. | -| Scanner Web + Worker | Scanner WebService Guild | `SCANNER-WEB-09-10x`, `SCANNER-RUNTIME-12-30x` (DONE 2025-10-18 -> 2025-10-24) | READY* | 2025-10-26T14:20Z | Orchestrator envelope work (`SCANNER-EVENTS-16-301/302`) still open; see gaps. | -| Concelier Core & Connectors | Concelier Core / Ops Guild | Ops runbook sign-off in `docs/ops/concelier-conflict-resolution.md` (2025-10-16) | READY | 2025-10-26T14:25Z | Conflict resolution & connector coverage accepted; Mongo schema hardening pending (see gaps). | -| Excititor API | Excititor Core Guild | Wave 0 connector ingest sign-offs (EXECPLAN.Section Wave 0) | READY | 2025-10-26T14:28Z | VEX linkset publishing complete for launch datasets. | -| Notify Web (legacy) | Notify Guild | Existing stack carried forward; Notifier program tracked separately (Sprint 38-40) | PENDING | 2025-10-26T14:32Z | Legacy notify web remains operational; migration to Notifier blocked on `SCANNER-EVENTS-16-301`. | -| Web UI | UI Guild | Stable build `registry.stella-ops.org/.../web-ui@sha256:10d9248...` deployed in stage and smoke-tested | READY | 2025-10-26T14:35Z | Policy editor GA items (Sprint 20) outside launch scope. | -| DevOps / Release | DevOps Guild | `deploy/tools/validate-profiles.sh` run (2025-10-26) covering dev/stage/prod/airgap/mirror | READY | 2025-10-26T15:02Z | Compose/Helm lint + docker compose config validated; see Section 2 for details. | -| Offline Kit | Offline Kit Guild | `DEVOPS-OFFLINE-18-004` (Go analyzer) and `DEVOPS-OFFLINE-18-005` (Python analyzer) complete; debug-store mirror pending (`DEVOPS-OFFLINE-17-004`). | PENDING | 2025-10-26T15:05Z | Awaiting release debug artefacts to finalise `DEVOPS-OFFLINE-17-004`; tracked in Section 3. | - -_\* READY with caveat - remaining work noted in Section 3._ - -## 2. Deployment Readiness Checklist - -- **Production profiles committed:** `deploy/compose/docker-compose.prod.yaml` and `deploy/helm/stellaops/values-prod.yaml` added with front-door network hand-off and secret references for Mongo/MinIO/core services. -- **Secrets placeholders documented:** `deploy/compose/env/prod.env.example` enumerates required credentials (`MONGO_INITDB_ROOT_PASSWORD`, `MINIO_ROOT_PASSWORD`, Redis/NATS endpoints, `FRONTDOOR_NETWORK`). Helm values reference Kubernetes secrets (`stellaops-prod-core`, `stellaops-prod-mongo`, `stellaops-prod-minio`, `stellaops-prod-notify`). -- **Static validation executed:** `deploy/tools/validate-profiles.sh` run on 2025-10-26 (docker compose config + helm lint/template) with all profiles passing. -- **Ingress model defined:** Production compose profile introduces external `frontdoor` network; README updated with creation instructions and scope of externally reachable services. -- **Observability hooks:** Authority/Signer/Attestor telemetry packs verified; scanner runtime build-id metrics landed (`SCANNER-RUNTIME-17-401`). Grafana dashboards referenced in component runbooks. -- **Rollback assets:** Stage Compose profile remains aligned (`docker-compose.stage.yaml`), enabling rehearsals before prod cutover; release manifests (`deploy/releases/2025.09-stable.yaml`) map digests for reproducible rollback. -- **Rehearsal status:** 2025-10-26 validation dry-run executed (`deploy/tools/validate-profiles.sh` across dev/stage/prod/airgap/mirror). Full stage Helm rollout pending access to the managed staging cluster; target to complete once credentials are provisioned. - -## 3. Outstanding Gaps & Follow-ups - -| Item | Owner | Tracking Ref | Target / Next Step | Impact | -| --- | --- | --- | --- | --- | -| Tenant scope propagation and audit coverage | Authority Core Guild | `AUTH-AOC-19-002` (DOING 2025-10-26) | Land enforcement + audit fixtures by Sprint 19 freeze | Medium - required for multi-tenant GA but does not block initial cutover if tenants scoped manually. | -| Orchestrator event envelopes + Notifier handshake | Scanner WebService Guild | `SCANNER-EVENTS-16-301` (BLOCKED), `SCANNER-EVENTS-16-302` (DOING) | Coordinate with Gateway/Notifier owners on preview package replacement or binding redirects; rerun `dotnet test` once patch lands and refresh schema docs. Share envelope samples in `docs/events/` after tests pass. | High — gating Notifier migration; legacy notify path remains functional meanwhile. | -| Offline Kit Python analyzer bundle | Offline Kit Guild + Scanner Guild | `DEVOPS-OFFLINE-18-005` (DONE 2025-10-26) | Monitor for follow-up manifest updates and rerun smoke script when analyzers change. | Medium - ensures language analyzer coverage stays current for offline installs. | -| Offline Kit debug store mirror | Offline Kit Guild + DevOps Guild | `DEVOPS-OFFLINE-17-004` (BLOCKED 2025-10-26) | Release pipeline must publish `out/release/debug` artefacts; once available, run `mirror_debug_store.py` and commit `metadata/debug-store.json`. | Low - symbol lookup remains accessible from staging assets but required before next Offline Kit tag. | -| Mongo schema validators for advisory ingestion | Concelier Storage Guild | `CONCELIER-STORE-AOC-19-001` (TODO) | Finalize JSON schema + migration toggles; coordinate with Ops for rollout window | Low - current validation handled in app layer; schema guard adds defense-in-depth. | -| Authority plugin telemetry alignment | Security Guild | `SEC2.PLG`, `SEC3.PLG`, `SEC5.PLG` (BLOCKED pending AUTH DPoP/MTLS tasks) | Resume once upstream auth surfacing stabilises | Low - plugin remains optional; launch uses default Authority configuration. | - -## 4. Approvals & Distribution - -- Record shared in `#launch-readiness` (Mattermost) 2025-10-26 15:15 UTC with DevOps + Guild leads for acknowledgement. -- Updates to this document require dual sign-off from DevOps Guild (owner) and impacted module guild lead; retain change log via Git history. -- Cutover rehearsal and rollback drills are tracked separately in `docs/ops/launch-cutover.md` (see associated Task `DEVOPS-LAUNCH-18-001`). *** End Patch +# Launch Readiness Record - Stella Ops + +_Updated: 2025-10-26 (UTC)_ + +This document captures production launch sign-offs, deployment readiness checkpoints, and any open risks that must be tracked before GA cutover. + +## 1. Sign-off Summary + +| Module / Service | Guild / Point of Contact | Evidence (Task or Runbook) | Status | Timestamp (UTC) | Notes | +| --- | --- | --- | --- | --- | --- | +| Authority (Issuer) | Authority Core Guild | `AUTH-AOC-19-001` - scope issuance & configuration complete (DONE 2025-10-26) | READY | 2025-10-26T14:05Z | Tenant scope propagation follow-up (`AUTH-AOC-19-002`) tracked in gaps section. | +| Signer | Signer Guild | `SIGNER-API-11-101` / `SIGNER-REF-11-102` / `SIGNER-QUOTA-11-103` (DONE 2025-10-21) | READY | 2025-10-26T14:07Z | DSSE signing, referrer verification, and quota enforcement validated in CI. | +| Attestor | Attestor Guild | `ATTESTOR-API-11-201` / `ATTESTOR-VERIFY-11-202` / `ATTESTOR-OBS-11-203` (DONE 2025-10-19) | READY | 2025-10-26T14:10Z | Rekor submission/verification pipeline green; telemetry pack published. | +| Scanner Web + Worker | Scanner WebService Guild | `SCANNER-WEB-09-10x`, `SCANNER-RUNTIME-12-30x` (DONE 2025-10-18 -> 2025-10-24) | READY* | 2025-10-26T14:20Z | Orchestrator envelope work (`SCANNER-EVENTS-16-301/302`) still open; see gaps. | +| Concelier Core & Connectors | Concelier Core / Ops Guild | Ops runbook sign-off in `docs/modules/concelier/operations/conflict-resolution.md` (2025-10-16) | READY | 2025-10-26T14:25Z | Conflict resolution & connector coverage accepted; Mongo schema hardening pending (see gaps). | +| Excititor API | Excititor Core Guild | Wave 0 connector ingest sign-offs (EXECPLAN.Section Wave 0) | READY | 2025-10-26T14:28Z | VEX linkset publishing complete for launch datasets. | +| Notify Web (legacy) | Notify Guild | Existing stack carried forward; Notifier program tracked separately (Sprint 38-40) | PENDING | 2025-10-26T14:32Z | Legacy notify web remains operational; migration to Notifier blocked on `SCANNER-EVENTS-16-301`. | +| Web UI | UI Guild | Stable build `registry.stella-ops.org/.../web-ui@sha256:10d9248...` deployed in stage and smoke-tested | READY | 2025-10-26T14:35Z | Policy editor GA items (Sprint 20) outside launch scope. | +| DevOps / Release | DevOps Guild | `deploy/tools/validate-profiles.sh` run (2025-10-26) covering dev/stage/prod/airgap/mirror | READY | 2025-10-26T15:02Z | Compose/Helm lint + docker compose config validated; see Section 2 for details. | +| Offline Kit | Offline Kit Guild | `DEVOPS-OFFLINE-18-004` (Go analyzer) and `DEVOPS-OFFLINE-18-005` (Python analyzer) complete; debug-store mirror pending (`DEVOPS-OFFLINE-17-004`). | PENDING | 2025-10-26T15:05Z | Awaiting release debug artefacts to finalise `DEVOPS-OFFLINE-17-004`; tracked in Section 3. | + +_\* READY with caveat - remaining work noted in Section 3._ + +## 2. Deployment Readiness Checklist + +- **Production profiles committed:** `deploy/compose/docker-compose.prod.yaml` and `deploy/helm/stellaops/values-prod.yaml` added with front-door network hand-off and secret references for Mongo/MinIO/core services. +- **Secrets placeholders documented:** `deploy/compose/env/prod.env.example` enumerates required credentials (`MONGO_INITDB_ROOT_PASSWORD`, `MINIO_ROOT_PASSWORD`, Redis/NATS endpoints, `FRONTDOOR_NETWORK`). Helm values reference Kubernetes secrets (`stellaops-prod-core`, `stellaops-prod-mongo`, `stellaops-prod-minio`, `stellaops-prod-notify`). +- **Static validation executed:** `deploy/tools/validate-profiles.sh` run on 2025-10-26 (docker compose config + helm lint/template) with all profiles passing. +- **Ingress model defined:** Production compose profile introduces external `frontdoor` network; README updated with creation instructions and scope of externally reachable services. +- **Observability hooks:** Authority/Signer/Attestor telemetry packs verified; scanner runtime build-id metrics landed (`SCANNER-RUNTIME-17-401`). Grafana dashboards referenced in component runbooks. +- **Rollback assets:** Stage Compose profile remains aligned (`docker-compose.stage.yaml`), enabling rehearsals before prod cutover; release manifests (`deploy/releases/2025.09-stable.yaml`) map digests for reproducible rollback. +- **Rehearsal status:** 2025-10-26 validation dry-run executed (`deploy/tools/validate-profiles.sh` across dev/stage/prod/airgap/mirror). Full stage Helm rollout pending access to the managed staging cluster; target to complete once credentials are provisioned. + +## 3. Outstanding Gaps & Follow-ups + +| Item | Owner | Tracking Ref | Target / Next Step | Impact | +| --- | --- | --- | --- | --- | +| Tenant scope propagation and audit coverage | Authority Core Guild | `AUTH-AOC-19-002` (DOING 2025-10-26) | Land enforcement + audit fixtures by Sprint 19 freeze | Medium - required for multi-tenant GA but does not block initial cutover if tenants scoped manually. | +| Orchestrator event envelopes + Notifier handshake | Scanner WebService Guild | `SCANNER-EVENTS-16-301` (BLOCKED), `SCANNER-EVENTS-16-302` (DOING) | Coordinate with Gateway/Notifier owners on preview package replacement or binding redirects; rerun `dotnet test` once patch lands and refresh schema docs. Share envelope samples in `docs/events/` after tests pass. | High — gating Notifier migration; legacy notify path remains functional meanwhile. | +| Offline Kit Python analyzer bundle | Offline Kit Guild + Scanner Guild | `DEVOPS-OFFLINE-18-005` (DONE 2025-10-26) | Monitor for follow-up manifest updates and rerun smoke script when analyzers change. | Medium - ensures language analyzer coverage stays current for offline installs. | +| Offline Kit debug store mirror | Offline Kit Guild + DevOps Guild | `DEVOPS-OFFLINE-17-004` (BLOCKED 2025-10-26) | Release pipeline must publish `out/release/debug` artefacts; once available, run `mirror_debug_store.py` and commit `metadata/debug-store.json`. | Low - symbol lookup remains accessible from staging assets but required before next Offline Kit tag. | +| Mongo schema validators for advisory ingestion | Concelier Storage Guild | `CONCELIER-STORE-AOC-19-001` (TODO) | Finalize JSON schema + migration toggles; coordinate with Ops for rollout window | Low - current validation handled in app layer; schema guard adds defense-in-depth. | +| Authority plugin telemetry alignment | Security Guild | `SEC2.PLG`, `SEC3.PLG`, `SEC5.PLG` (BLOCKED pending AUTH DPoP/MTLS tasks) | Resume once upstream auth surfacing stabilises | Low - plugin remains optional; launch uses default Authority configuration. | + +## 4. Approvals & Distribution + +- Record shared in `#launch-readiness` (Mattermost) 2025-10-26 15:15 UTC with DevOps + Guild leads for acknowledgement. +- Updates to this document require dual sign-off from DevOps Guild (owner) and impacted module guild lead; retain change log via Git history. +- Cutover rehearsal and rollback drills are tracked separately in `docs/modules/devops/runbooks/launch-cutover.md` (see associated Task `DEVOPS-LAUNCH-18-001`). *** End Patch diff --git a/docs/ops/nuget-preview-bootstrap.md b/docs/modules/devops/runbooks/nuget-preview-bootstrap.md similarity index 100% rename from docs/ops/nuget-preview-bootstrap.md rename to docs/modules/devops/runbooks/nuget-preview-bootstrap.md diff --git a/docs/modules/excititor/AGENTS.md b/docs/modules/excititor/AGENTS.md new file mode 100644 index 00000000..f7a5130a --- /dev/null +++ b/docs/modules/excititor/AGENTS.md @@ -0,0 +1,22 @@ +# Excititor agent guide + +## Mission +Excititor converts heterogeneous VEX feeds into raw observations and linksets that honour the Aggregation-Only Contract. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/excititor/README.md b/docs/modules/excititor/README.md new file mode 100644 index 00000000..51fbd50f --- /dev/null +++ b/docs/modules/excititor/README.md @@ -0,0 +1,33 @@ +# StellaOps Excititor + +Excititor converts heterogeneous VEX feeds into raw observations and linksets that honour the Aggregation-Only Contract. + +## Responsibilities +- Fetch OpenVEX/CSAF/CycloneDX statements via restart-only connectors. +- Store immutable VEX observations with full provenance. +- Publish linksets and events that drive policy suppression decisions. +- Provide deterministic exports for Offline Kit and downstream tooling. + +## Key components +- `StellaOps.Excititor.WebService` scheduler/API host. +- Connector libraries under `StellaOps.Excititor.Connector.*`. +- Normalization helpers and exporters in `StellaOps.Excititor.*`. + +## Integrations & dependencies +- Policy Engine for evidence queries. +- UI/CLI for conflict visibility and explanation. +- Notify for VEX-driven alerts. + +## Operational notes +- MongoDB for observation storage and job metadata. +- Offline kit packaging aligned with Concelier merges. +- Connector-specific runbooks (see `docs/modules/concelier/operations/connectors`). + +## Backlog references +- DOCS-LNM-22-006 / DOCS-LNM-22-007 (shared with Concelier). +- CLI-EXC-25-001..002 follow-up for CLI parity. + +## Epic alignment +- **Epic 1 – AOC enforcement:** maintain immutable VEX observations, provenance, and AOC verifier coverage. +- **Epic 7 – VEX Consensus Lens:** supply trustworthy raw inputs, trust metadata, and consensus hooks for the lens computations. +- **Epic 8 – Advisory AI:** expose citation-ready VEX payloads for the advisory assistant pipeline. diff --git a/docs/modules/excititor/TASKS.md b/docs/modules/excititor/TASKS.md new file mode 100644 index 00000000..98752f18 --- /dev/null +++ b/docs/modules/excititor/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Excititor + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| EXCITITOR-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| EXCITITOR-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| EXCITITOR-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_EXCITITOR.md b/docs/modules/excititor/architecture.md similarity index 83% rename from docs/ARCHITECTURE_EXCITITOR.md rename to docs/modules/excititor/architecture.md index 42d7a6ef..e95e168e 100644 --- a/docs/ARCHITECTURE_EXCITITOR.md +++ b/docs/modules/excititor/architecture.md @@ -1,32 +1,131 @@ # component_architecture_excititor.md — **Stella Ops Excititor** (Sprint 22) +> Consolidates the VEX ingestion guardrails from Epic 1 with consensus and AI-facing requirements from Epics 7 and 8. This is the authoritative architecture record for Excititor. + > **Scope.** This document specifies the **Excititor** service: its purpose, trust model, data structures, observation/linkset pipelines, APIs, plug-in contracts, storage schema, performance budgets, testing matrix, and how it integrates with Concelier, Policy Engine, and evidence surfaces. It is implementation-ready. - ---- - -## 0) Mission & role in the platform - + +--- + +## 0) Mission & role in the platform + **Mission.** Convert heterogeneous **VEX** statements (OpenVEX, CSAF VEX, CycloneDX VEX; vendor/distro/platform sources) into immutable **VEX observations**, correlate them into **linksets** that retain provenance/conflicts without precedence, and publish deterministic evidence exports and events that Policy Engine, Console, and CLI use to suppress or explain findings. - -**Boundaries.** - -* Excititor **does not** decide PASS/FAIL. It supplies **evidence** (statuses + justifications + provenance weights). + +**Boundaries.** + +* Excititor **does not** decide PASS/FAIL. It supplies **evidence** (statuses + justifications + provenance weights). * Excititor preserves **conflicting observations** unchanged; consensus (when enabled) merely annotates how policy might choose, but raw evidence remains exportable. -* VEX consumption is **backend‑only**: Scanner never applies VEX. The backend’s **Policy Engine** asks Excititor for status evidence and then decides what to show. - ---- - -## 1) Inputs, outputs & canonical domain - -### 1.1 Accepted input formats (ingest) - -* **OpenVEX** JSON documents (attested or raw). -* **CSAF VEX** 2.x (vendor PSIRTs and distros commonly publish CSAF). -* **CycloneDX VEX** 1.4+ (standalone VEX or embedded VEX blocks). -* **OCI‑attached attestations** (VEX statements shipped as OCI referrers) — optional connectors. - -All connectors register **source metadata**: provider identity, trust tier, signature expectations (PGP/cosign/PKI), fetch windows, rate limits, and time anchors. - +* VEX consumption is **backend-only**: Scanner never applies VEX. The backend’s **Policy Engine** asks Excititor for status evidence and then decides what to show. + +--- + +## 1) Aggregation guardrails (AOC baseline) + +Excititor enforces the same ingestion covenant as Concelier, tailored to VEX payloads: + +1. **Immutable `vex_raw` documents.** Upstream OpenVEX/CSAF/CycloneDX files are stored verbatim (`content.raw`) with provenance (`issuer`, `statement_id`, timestamps, signatures). Revisions append new versions linked by `supersedes`. +2. **No derived consensus at ingest time.** Fields such as `effective_status`, `merged_state`, `severity`, or reachability are forbidden. Roslyn analyzers and runtime guards block violations before writes. +3. **Linkset-only joins.** Product aliases, CVE keys, SBOM hints, and references live under `linkset`; ingestion must never mutate the underlying statement. +4. **Deterministic canonicalisation.** Writers sort JSON keys/arrays, normalize timestamps (UTC ISO‑8601), and hash content for reproducible exports. +5. **AOC verifier.** `StellaOps.AOC.Verifier` runs in CI and production, checking schema compliance, provenance completeness, sorted collections, and signature metadata. + +### 1.1 VEX raw document shape + +```json +{ + "_id": "vex_raw:openvex:VEX-2025-00001:v2", + "source": { + "issuer": "vendor:redhat", + "stream": "openvex", + "api": "https://vendor/api/vex/VEX-2025-00001.json", + "collector_version": "excititor/0.9.4" + }, + "upstream": { + "statement_id": "VEX-2025-00001", + "document_version": "2025-08-30T12:00:00Z", + "fetched_at": "2025-08-30T12:05:00Z", + "received_at": "2025-08-30T12:05:01Z", + "content_hash": "sha256:...", + "signature": { + "present": true, + "format": "dsse", + "key_id": "rekor:uuid", + "sig": "base64..." + } + }, + "content": { + "format": "openvex", + "spec_version": "1.0", + "raw": { /* upstream statement */ } + }, + "identifiers": { + "cve": ["CVE-2025-13579"], + "products": [ + {"purl": "pkg:rpm/redhat/openssl@3.0.9", "component": "openssl"} + ] + }, + "linkset": { + "aliases": ["REDHAT:RHSA-2025:1234"], + "sbom_products": ["pkg:rpm/redhat/openssl@3.0.9"], + "justifications": ["reasonable_worst_case_assumption"], + "references": [ + {"type": "advisory", "url": "https://..."} + ] + }, + "supersedes": "vex_raw:openvex:VEX-2025-00001:v1", + "tenant": "default" +} +``` + +### 1.2 Issuer trust registry + +To enable Epic 7’s consensus lens, Excititor maintains `vex_issuer_registry` documents containing: + +- `issuer_id`, canonical name, and allowed domains. +- `trust.tier` (`critical`, `high`, `medium`, `low`), `trust.confidence` (0–1). +- `products` PURL patterns the issuer is authoritative for. +- `signing_keys` with key IDs and expiry. +- `last_validated_at`, `revocation_status`. + +The registry is distributed as a signed bundle and cached locally; ingestion rejects statements from issuers without registry entries or valid signatures. + +### 1.3 Normalised tuple store + +Excititor derives `vex_normalized` tuples (without making decisions) for downstream consumers: + +```json +{ + "advisory_key": "CVE-2025-13579", + "artifact": "pkg:rpm/redhat/openssl@3.0.9", + "issuer": "vendor:redhat", + "status": "not_affected", + "justification": "component_not_present", + "scope": "runtime_path", + "timestamp": "2025-08-30T12:00:00Z", + "trust": {"tier": "high", "confidence": 0.95}, + "statement_id": "VEX-2025-00001:v2", + "content_hash": "sha256:..." +} +``` + +These tuples allow VEX Lens to compute deterministic consensus without re-parsing heavy upstream documents. + +### 1.4 AI-ready citations + +`GET /v1/vex/statements/{advisory_key}` produces sorted JSON responses containing raw statement metadata (`issuer`, `content_hash`, `signature`), normalised tuples, and provenance pointers. Advisory AI consumes this endpoint to build retrieval contexts with explicit citations. + +--- + +## 2) Inputs, outputs & canonical domain + +### 1.1 Accepted input formats (ingest) + +* **OpenVEX** JSON documents (attested or raw). +* **CSAF VEX** 2.x (vendor PSIRTs and distros commonly publish CSAF). +* **CycloneDX VEX** 1.4+ (standalone VEX or embedded VEX blocks). +* **OCI‑attached attestations** (VEX statements shipped as OCI referrers) — optional connectors. + +All connectors register **source metadata**: provider identity, trust tier, signature expectations (PGP/cosign/PKI), fetch windows, rate limits, and time anchors. + ### 1.2 Canonical model (observations & linksets) #### VexObservation @@ -142,45 +241,45 @@ Consensus persists only when Excititor policy adapters require pre-computed roll * **Index** — `(productKey, vulnerabilityId) → {status candidates, confidence, observationIds}` for high-speed joins. All exports remain deterministic and, when configured, attested via DSSE + Rekor v2. - ---- - -## 2) Identity model — products & joins - -### 2.1 Vuln identity - -* Accepts **CVE**, **GHSA**, vendor IDs (MSRC, RHSA…), distro IDs (DSA/USN/RHSA…) — normalized to `vulnId` with alias sets. -* **Alias graph** maintained (from Concelier) to map vendor/distro IDs → CVE (primary) and to **GHSA** where applicable. - -### 2.2 Product identity (`productKey`) - -* **Primary:** `purl` (Package URL). -* **Secondary links:** `cpe`, **OS package NVRA/EVR**, NuGet/Maven/Golang identity, and **OS package name** when purl unavailable. -* **Fallback:** `oci:/@` for image‑level VEX. -* **Special cases:** kernel modules, firmware, platforms → provider‑specific mapping helpers (connector captures provider’s product taxonomy → canonical `productKey`). - -> Excititor does not invent identities. If a provider cannot be mapped to purl/CPE/NVRA deterministically, we keep the native **product string** and mark the claim as **non‑joinable**; the backend will ignore it unless a policy explicitly whitelists that provider mapping. - ---- - -## 3) Storage schema (MongoDB) - -Database: `excititor` - -### 3.1 Collections - -**`vex.providers`** - -``` -_id: providerId -name, homepage, contact -trustTier: enum {vendor, distro, platform, hub, attestation} -signaturePolicy: { type: pgp|cosign|x509|none, keys[], certs[], cosignKeylessRoots[] } -fetch: { baseUrl, kind: http|oci|file, rateLimit, etagSupport, windowDays } -enabled: bool -createdAt, modifiedAt -``` - + +--- + +## 3) Identity model — products & joins + +### 2.1 Vuln identity + +* Accepts **CVE**, **GHSA**, vendor IDs (MSRC, RHSA…), distro IDs (DSA/USN/RHSA…) — normalized to `vulnId` with alias sets. +* **Alias graph** maintained (from Concelier) to map vendor/distro IDs → CVE (primary) and to **GHSA** where applicable. + +### 2.2 Product identity (`productKey`) + +* **Primary:** `purl` (Package URL). +* **Secondary links:** `cpe`, **OS package NVRA/EVR**, NuGet/Maven/Golang identity, and **OS package name** when purl unavailable. +* **Fallback:** `oci:/@` for image‑level VEX. +* **Special cases:** kernel modules, firmware, platforms → provider‑specific mapping helpers (connector captures provider’s product taxonomy → canonical `productKey`). + +> Excititor does not invent identities. If a provider cannot be mapped to purl/CPE/NVRA deterministically, we keep the native **product string** and mark the claim as **non‑joinable**; the backend will ignore it unless a policy explicitly whitelists that provider mapping. + +--- + +## 4) Storage schema (MongoDB) + +Database: `excititor` + +### 3.1 Collections + +**`vex.providers`** + +``` +_id: providerId +name, homepage, contact +trustTier: enum {vendor, distro, platform, hub, attestation} +signaturePolicy: { type: pgp|cosign|x509|none, keys[], certs[], cosignKeylessRoots[] } +fetch: { baseUrl, kind: http|oci|file, rateLimit, etagSupport, windowDays } +enabled: bool +createdAt, modifiedAt +``` + **`vex.raw`** (immutable raw documents) ``` @@ -247,7 +346,7 @@ correlation: { replaces?: sha256, replacedBy?: sha256 } ``` * Indexes: `{tenant:1, key.vulnerabilityId:1, key.productKey:1}`, `{tenant:1, purls:1}`, `{tenant:1, updatedAt:-1}`. - + **`vex.events`** (observation/linkset events, optional long retention) ``` @@ -281,18 +380,18 @@ consensusDigest * Indexes: `{vulnerabilityId:1, productKey:1}`, `{policyRevisionId:1, evaluatedAt:-1}`. **`vex.exports`** (manifest of emitted artifacts) - -``` -_id -querySignature -format: raw|consensus|index -artifactSha256 -rekor { uuid, index, url }? -createdAt -policyRevisionId -cacheable: bool -``` - + +``` +_id +querySignature +format: raw|consensus|index +artifactSha256 +rekor { uuid, index, url }? +createdAt +policyRevisionId +cacheable: bool +``` + **`vex.cache`** — observation/linkset export cache: `{querySignature, exportId, ttl, hits}`. **`vex.migrations`** — ordered migrations ensuring new indexes (`20251027-linksets-introduced`, etc.). @@ -302,14 +401,14 @@ cacheable: bool * Hot path queries rely on `{tenant, key.vulnerabilityId, key.productKey}` covering linkset lookup. * Observability queries use `{tenant, updatedAt}` to monitor staleness. * Consensus (if enabled) keyed by `{vulnerabilityId, productKey, policyRevisionId}` for deterministic reuse. - ---- - -## 4) Ingestion pipeline - -### 4.1 Connector contract - -```csharp + +--- + +## 5) Ingestion pipeline + +### 4.1 Connector contract + +```csharp public interface IVexConnector { string ProviderId { get; } @@ -320,85 +419,85 @@ public interface IVexConnector * **Fetch** must implement: window scheduling, conditional GET (ETag/If‑Modified‑Since), rate limiting, retry/backoff. * **Normalize** parses the format, validates schema, maps product identities deterministically, emits observation statements with **provenance** metadata (locator, justification, version ranges). - -### 4.2 Signature verification (per provider) - -* **cosign (keyless or keyful)** for OCI referrers or HTTP‑served JSON with Sigstore bundles. -* **PGP** (provider keyrings) for distro/vendor feeds that sign docs. -* **x509** (mutual TLS / provider‑pinned certs) where applicable. + +### 4.2 Signature verification (per provider) + +* **cosign (keyless or keyful)** for OCI referrers or HTTP‑served JSON with Sigstore bundles. +* **PGP** (provider keyrings) for distro/vendor feeds that sign docs. +* **x509** (mutual TLS / provider‑pinned certs) where applicable. * Signature state is stored on **vex.raw.sig** and copied into `statements[].signatureState` so downstream policy can gate by verification result. > Observation statements from sources failing signature policy are marked `"signatureState.verified=false"` and policy can down-weight or ignore them. - -### 4.3 Time discipline - -* For each doc, prefer **provider’s document timestamp**; if absent, use fetch time. + +### 4.3 Time discipline + +* For each doc, prefer **provider’s document timestamp**; if absent, use fetch time. * Statements carry `lastObserved` which drives **tie-breaking** within equal weight tiers. - ---- - -## 5) Normalization: product & status semantics - -### 5.1 Product mapping - -* **purl** first; **cpe** second; OS package NVRA/EVR mapping helpers (distro connectors) produce purls via canonical tables (e.g., rpm→purl:rpm, deb→purl:deb). -* Where a provider publishes **platform‑level** VEX (e.g., “RHEL 9 not affected”), connectors expand to known product inventory rules (e.g., map to sets of packages/components shipped in the platform). Expansion tables are versioned and kept per provider; every expansion emits **evidence** indicating the rule applied. + +--- + +## 6) Normalization: product & status semantics + +### 5.1 Product mapping + +* **purl** first; **cpe** second; OS package NVRA/EVR mapping helpers (distro connectors) produce purls via canonical tables (e.g., rpm→purl:rpm, deb→purl:deb). +* Where a provider publishes **platform‑level** VEX (e.g., “RHEL 9 not affected”), connectors expand to known product inventory rules (e.g., map to sets of packages/components shipped in the platform). Expansion tables are versioned and kept per provider; every expansion emits **evidence** indicating the rule applied. * If expansion would be speculative, the statement remains **platform-scoped** with `productKey="platform:redhat:rhel:9"` and is flagged **non-joinable**; backend can decide to use platform VEX only when Scanner proves the platform runtime. - -### 5.2 Status + justification mapping - -* Canonical **status**: `affected | not_affected | fixed | under_investigation`. -* **Justifications** normalized to a controlled vocabulary (CISA‑aligned), e.g.: - - * `component_not_present` - * `vulnerable_code_not_in_execute_path` - * `vulnerable_configuration_unused` - * `inline_mitigation_applied` - * `fix_available` (with `fixedVersion`) - * `under_investigation` -* Providers with free‑text justifications are mapped by deterministic tables; raw text preserved as `evidence`. - ---- - -## 6) Consensus algorithm - + +### 5.2 Status + justification mapping + +* Canonical **status**: `affected | not_affected | fixed | under_investigation`. +* **Justifications** normalized to a controlled vocabulary (CISA‑aligned), e.g.: + + * `component_not_present` + * `vulnerable_code_not_in_execute_path` + * `vulnerable_configuration_unused` + * `inline_mitigation_applied` + * `fix_available` (with `fixedVersion`) + * `under_investigation` +* Providers with free‑text justifications are mapped by deterministic tables; raw text preserved as `evidence`. + +--- + +## 7) Consensus algorithm + **Goal:** produce a **stable**, explainable `rollupStatus` per `(vulnId, productKey)` when consumers opt into Excititor-managed consensus derived from linksets. - -### 6.1 Inputs - + +### 6.1 Inputs + * Set **S** of observation statements drawn from the current `VexLinkset` for `(tenant, vulnId, productKey)`. -* **Excititor policy snapshot**: - - * **weights** per provider tier and per provider overrides. - * **justification gates** (e.g., require justification for `not_affected` to be acceptable). - * **minEvidence** rules (e.g., `not_affected` must come from ≥1 vendor or 2 distros). - * **signature requirements** (e.g., require verified signature for ‘fixed’ to be considered). - -### 6.2 Steps - +* **Excititor policy snapshot**: + + * **weights** per provider tier and per provider overrides. + * **justification gates** (e.g., require justification for `not_affected` to be acceptable). + * **minEvidence** rules (e.g., `not_affected` must come from ≥1 vendor or 2 distros). + * **signature requirements** (e.g., require verified signature for ‘fixed’ to be considered). + +### 6.2 Steps + 1. **Filter invalid** statements by signature policy & justification gates → set `S'`. 2. **Score** each statement: `score = weight(provider) * freshnessFactor(lastObserved)` where freshnessFactor ∈ [0.8, 1.0] for staleness decay (configurable; small effect). Observations lacking verified signatures receive policy-configured penalties. 3. **Aggregate** scores per status: `W(status) = Σ score(statements with that status)`. -4. **Pick** `rollupStatus = argmax_status W(status)`. -5. **Tie‑breakers** (in order): - - * Higher **max single** provider score wins (vendor > distro > platform > hub). - * More **recent** lastObserved wins. - * Deterministic lexicographic order of status (`fixed` > `not_affected` > `under_investigation` > `affected`) as final tiebreaker. +4. **Pick** `rollupStatus = argmax_status W(status)`. +5. **Tie‑breakers** (in order): + + * Higher **max single** provider score wins (vendor > distro > platform > hub). + * More **recent** lastObserved wins. + * Deterministic lexicographic order of status (`fixed` > `not_affected` > `under_investigation` > `affected`) as final tiebreaker. 6. **Explain**: mark accepted observations (`accepted=true; reason="weight"`/`"freshness"`/`"confidence"`) and rejected ones with explicit `reason` (`"insufficient_justification"`, `"signature_unverified"`, `"lower_weight"`, `"low_confidence_linkset"`). - + > The algorithm is **pure** given `S` and policy snapshot; result is reproducible and hashed into `consensusDigest`. - ---- - -## 7) Query & export APIs - -All endpoints are versioned under `/api/v1/vex`. - -### 7.1 Query (online) - -``` + +--- + +## 8) Query & export APIs + +All endpoints are versioned under `/api/v1/vex`. + +### 7.1 Query (online) + +``` POST /observations/search body: { vulnIds?: string[], productKeys?: string[], providers?: string[], since?: timestamp, limit?: int, pageToken?: string } → { observations[], nextPageToken? } @@ -406,100 +505,100 @@ POST /observations/search POST /linksets/search body: { vulnIds?: string[], productKeys?: string[], confidence?: string[], since?: timestamp, limit?: int, pageToken?: string } → { linksets[], nextPageToken? } - -POST /consensus/search - body: { vulnIds?: string[], productKeys?: string[], policyRevisionId?: string, since?: timestamp, limit?: int, pageToken?: string } - → { entries[], nextPageToken? } - + +POST /consensus/search + body: { vulnIds?: string[], productKeys?: string[], policyRevisionId?: string, since?: timestamp, limit?: int, pageToken?: string } + → { entries[], nextPageToken? } + POST /excititor/resolve (scope: vex.read) body: { productKeys?: string[], purls?: string[], vulnerabilityIds: string[], policyRevisionId?: string } → { policy, resolvedAt, results: [ { vulnerabilityId, productKey, status, observations[], conflicts[], linksetConfidence, consensus?, signals?, envelope? } ] } -``` - -### 7.2 Exports (cacheable snapshots) - -``` -POST /exports - body: { signature: { vulnFilter?, productFilter?, providers?, since? }, format: raw|consensus|index, policyRevisionId?: string, force?: bool } - → { exportId, artifactSha256, rekor? } - -GET /exports/{exportId} → bytes (application/json or binary index) -GET /exports/{exportId}/meta → { signature, policyRevisionId, createdAt, artifactSha256, rekor? } -``` - -### 7.3 Provider operations - -``` -GET /providers → provider list & signature policy -POST /providers/{id}/refresh → trigger fetch/normalize window -GET /providers/{id}/status → last fetch, doc counts, signature stats -``` - -**Auth:** service‑to‑service via Authority tokens; operator operations via UI/CLI with RBAC. - ---- - -## 8) Attestation integration - -* Exports can be **DSSE‑signed** via **Signer** and logged to **Rekor v2** via **Attestor** (optional but recommended for regulated pipelines). -* `vex.exports.rekor` stores `{uuid, index, url}` when present. -* **Predicate type**: `https://stella-ops.org/attestations/vex-export/1` with fields: - - * `querySignature`, `policyRevisionId`, `artifactSha256`, `createdAt`. - ---- - -## 9) Configuration (YAML) - -```yaml -excititor: - mongo: { uri: "mongodb://mongo/excititor" } - s3: - endpoint: http://minio:9000 - bucket: stellaops - policy: - weights: - vendor: 1.0 - distro: 0.9 - platform: 0.7 - hub: 0.5 - attestation: 0.6 - ceiling: 1.25 - scoring: - alpha: 0.25 - beta: 0.5 - providerOverrides: - redhat: 1.0 - suse: 0.95 - requireJustificationForNotAffected: true - signatureRequiredForFixed: true - minEvidence: - not_affected: - vendorOrTwoDistros: true - connectors: - - providerId: redhat - kind: csaf - baseUrl: https://access.redhat.com/security/data/csaf/v2/ - signaturePolicy: { type: pgp, keys: [ "…redhat-pgp-key…" ] } - windowDays: 7 - - providerId: suse - kind: csaf - baseUrl: https://ftp.suse.com/pub/projects/security/csaf/ - signaturePolicy: { type: pgp, keys: [ "…suse-pgp-key…" ] } - - providerId: ubuntu - kind: openvex - baseUrl: https://…/vex/ - signaturePolicy: { type: none } - - providerId: vendorX - kind: cyclonedx-vex - ociRef: ghcr.io/vendorx/vex@sha256:… - signaturePolicy: { type: cosign, cosignKeylessRoots: [ "sigstore-root" ] } -``` - -### 9.1 WebService endpoints - -With storage configured, the WebService exposes the following ingress and diagnostic APIs: - +``` + +### 7.2 Exports (cacheable snapshots) + +``` +POST /exports + body: { signature: { vulnFilter?, productFilter?, providers?, since? }, format: raw|consensus|index, policyRevisionId?: string, force?: bool } + → { exportId, artifactSha256, rekor? } + +GET /exports/{exportId} → bytes (application/json or binary index) +GET /exports/{exportId}/meta → { signature, policyRevisionId, createdAt, artifactSha256, rekor? } +``` + +### 7.3 Provider operations + +``` +GET /providers → provider list & signature policy +POST /providers/{id}/refresh → trigger fetch/normalize window +GET /providers/{id}/status → last fetch, doc counts, signature stats +``` + +**Auth:** service‑to‑service via Authority tokens; operator operations via UI/CLI with RBAC. + +--- + +## 9) Attestation integration + +* Exports can be **DSSE‑signed** via **Signer** and logged to **Rekor v2** via **Attestor** (optional but recommended for regulated pipelines). +* `vex.exports.rekor` stores `{uuid, index, url}` when present. +* **Predicate type**: `https://stella-ops.org/attestations/vex-export/1` with fields: + + * `querySignature`, `policyRevisionId`, `artifactSha256`, `createdAt`. + +--- + +## 10) Configuration (YAML) + +```yaml +excititor: + mongo: { uri: "mongodb://mongo/excititor" } + s3: + endpoint: http://minio:9000 + bucket: stellaops + policy: + weights: + vendor: 1.0 + distro: 0.9 + platform: 0.7 + hub: 0.5 + attestation: 0.6 + ceiling: 1.25 + scoring: + alpha: 0.25 + beta: 0.5 + providerOverrides: + redhat: 1.0 + suse: 0.95 + requireJustificationForNotAffected: true + signatureRequiredForFixed: true + minEvidence: + not_affected: + vendorOrTwoDistros: true + connectors: + - providerId: redhat + kind: csaf + baseUrl: https://access.redhat.com/security/data/csaf/v2/ + signaturePolicy: { type: pgp, keys: [ "…redhat-pgp-key…" ] } + windowDays: 7 + - providerId: suse + kind: csaf + baseUrl: https://ftp.suse.com/pub/projects/security/csaf/ + signaturePolicy: { type: pgp, keys: [ "…suse-pgp-key…" ] } + - providerId: ubuntu + kind: openvex + baseUrl: https://…/vex/ + signaturePolicy: { type: none } + - providerId: vendorX + kind: cyclonedx-vex + ociRef: ghcr.io/vendorx/vex@sha256:… + signaturePolicy: { type: cosign, cosignKeylessRoots: [ "sigstore-root" ] } +``` + +### 9.1 WebService endpoints + +With storage configured, the WebService exposes the following ingress and diagnostic APIs: + * `GET /excititor/status` – returns the active storage configuration and registered artifact stores. * `GET /excititor/health` – simple liveness probe. * `POST /excititor/statements` – accepts normalized VEX statements and persists them via `IVexClaimStore`; use this for migrations/backfills. @@ -507,36 +606,36 @@ With storage configured, the WebService exposes the following ingress and diagno * `POST /excititor/resolve` – requires `vex.read` scope; accepts up to 256 `(vulnId, productKey)` pairs via `productKeys` or `purls` and returns deterministic consensus results, decision telemetry, and a signed envelope (`artifact` digest, optional signer signature, optional attestation metadata + DSSE envelope). Returns **409 Conflict** when the requested `policyRevisionId` mismatches the active snapshot. Run the ingestion endpoint once after applying migration `20251019-consensus-signals-statements` to repopulate historical statements with the new severity/KEV/EPSS signal fields. - -* `weights.ceiling` raises the deterministic clamp applied to provider tiers/overrides (range 1.0‒5.0). Values outside the range are clamped with warnings so operators can spot typos. -* `scoring.alpha` / `scoring.beta` configure KEV/EPSS boosts for the Phase 1 → Phase 2 scoring pipeline. Defaults (0.25, 0.5) preserve prior behaviour; negative or excessively large values fall back with diagnostics. - ---- - -## 10) Security model - -* **Input signature verification** enforced per provider policy (PGP, cosign, x509). -* **Connector allowlists**: outbound fetch constrained to configured domains. -* **Tenant isolation**: per‑tenant DB prefixes or separate DBs; per‑tenant S3 prefixes; per‑tenant policies. -* **AuthN/Z**: Authority‑issued OpToks; RBAC roles (`vex.read`, `vex.admin`, `vex.export`). + +* `weights.ceiling` raises the deterministic clamp applied to provider tiers/overrides (range 1.0‒5.0). Values outside the range are clamped with warnings so operators can spot typos. +* `scoring.alpha` / `scoring.beta` configure KEV/EPSS boosts for the Phase 1 → Phase 2 scoring pipeline. Defaults (0.25, 0.5) preserve prior behaviour; negative or excessively large values fall back with diagnostics. + +--- + +## 11) Security model + +* **Input signature verification** enforced per provider policy (PGP, cosign, x509). +* **Connector allowlists**: outbound fetch constrained to configured domains. +* **Tenant isolation**: per‑tenant DB prefixes or separate DBs; per‑tenant S3 prefixes; per‑tenant policies. +* **AuthN/Z**: Authority‑issued OpToks; RBAC roles (`vex.read`, `vex.admin`, `vex.export`). * **No secrets in logs**; deterministic logging contexts include providerId, docDigest, observationId, and linksetId. - ---- - -## 11) Performance & scale - + +--- + +## 12) Performance & scale + * **Targets:** * Normalize 10k observation statements/minute/core. * Linkset rebuild ≤ 20 ms P95 for 1k unique `(vuln, product)` pairs in hot cache. * Consensus (when enabled) compute ≤ 50 ms for 1k unique `(vuln, product)` pairs. * Export (observations + linksets) 1M rows in ≤ 60 s on 8 cores with streaming writer. - -* **Scaling:** - - * WebService handles control APIs; **Worker** background services (same image) execute fetch/normalize in parallel with rate‑limits; Mongo writes batched; upserts by natural keys. - * Exports stream straight to S3 (MinIO) with rolling buffers. - + +* **Scaling:** + + * WebService handles control APIs; **Worker** background services (same image) execute fetch/normalize in parallel with rate‑limits; Mongo writes batched; upserts by natural keys. + * Exports stream straight to S3 (MinIO) with rolling buffers. + * **Caching:** * `vex.cache` maps query signatures → export; TTL to avoid stampedes; optimistic reuse unless `force`. @@ -573,11 +672,11 @@ Excititor.Worker ships with a background refresh service that re-evaluates stale * `ConsensusTtl` governs when the worker issues a fresh resolve for cached consensus data. * `Damper` lengths are clamped between `Minimum`/`Maximum`; duration is bypassed when component fingerprints (`VexProduct.ComponentIdentifiers`) change. * The same keys are available through environment variables (e.g., `Excititor__Worker__Refresh__ConsensusTtl=02:00:00`). - ---- - -## 12) Observability - + +--- + +## 13) Observability + * **Metrics:** * `vex.fetch.requests_total{provider}` / `vex.fetch.bytes_total{provider}` @@ -589,62 +688,62 @@ Excititor.Worker ships with a background refresh service that re-evaluates stale * `vex.exports.bytes_total{format}` / `vex.exports.latency_seconds{format}` * **Tracing:** spans for fetch, verify, parse, map, observe, linkset, consensus, export. * **Dashboards:** provider staleness, linkset conflict hot spots, signature posture, export cache hit-rate. - ---- - -## 13) Testing matrix - + +--- + +## 14) Testing matrix + * **Connectors:** golden raw docs → deterministic observation statements (fixtures per provider/format). -* **Signature policies:** valid/invalid PGP/cosign/x509 samples; ensure rejects are recorded but not accepted. +* **Signature policies:** valid/invalid PGP/cosign/x509 samples; ensure rejects are recorded but not accepted. * **Normalization edge cases:** platform-scoped statements, free-text justifications, non-purl products. * **Linksets:** conflict scenarios across tiers; verify confidence scoring + conflict payload stability. * **Consensus (optional):** ensure tie-breakers honour policy weights/justification gates. * **Performance:** 1M-row observation/linkset export timing; memory ceilings; stream correctness. * **Determinism:** same inputs + policy → identical linkset hashes, conflict payloads, optional `consensusDigest`, and export bytes. -* **API contract tests:** pagination, filters, RBAC, rate limits. - ---- - -## 14) Integration points - +* **API contract tests:** pagination, filters, RBAC, rate limits. + +--- + +## 15) Integration points + * **Backend Policy Engine** (in Scanner.WebService): calls `POST /excititor/resolve` (scope `vex.read`) with batched `(purl, vulnId)` pairs to fetch `rollupStatus + sources`. -* **Concelier**: provides alias graph (CVE↔vendor IDs) and may supply VEX‑adjacent metadata (e.g., KEV flag) for policy escalation. +* **Concelier**: provides alias graph (CVE↔vendor IDs) and may supply VEX‑adjacent metadata (e.g., KEV flag) for policy escalation. * **UI**: VEX explorer screens use `/observations/search`, `/linksets/search`, and `/consensus/search`; show conflicts & provenance. * **CLI**: `stella vex linksets export --since 7d --out vex-linksets.json` (optionally `--include-consensus`) for audits and Offline Kit parity. - ---- - -## 15) Failure modes & fallback - -* **Provider unreachable:** stale thresholds trigger warnings; policy can down‑weight stale providers automatically (freshness factor). -* **Signature outage:** continue to ingest but mark `signatureState.verified=false`; consensus will likely exclude or down‑weight per policy. -* **Schema drift:** unknown fields are preserved as `evidence`; normalization rejects only on **invalid identity** or **status**. - ---- - -## 16) Rollout plan (incremental) - + +--- + +## 16) Failure modes & fallback + +* **Provider unreachable:** stale thresholds trigger warnings; policy can down‑weight stale providers automatically (freshness factor). +* **Signature outage:** continue to ingest but mark `signatureState.verified=false`; consensus will likely exclude or down‑weight per policy. +* **Schema drift:** unknown fields are preserved as `evidence`; normalization rejects only on **invalid identity** or **status**. + +--- + +## 17) Rollout plan (incremental) + 1. **MVP**: OpenVEX + CSAF connectors for 3 major providers (e.g., Red Hat/SUSE/Ubuntu), normalization + consensus + `/excititor/resolve`. -2. **Signature policies**: PGP for distros; cosign for OCI. -3. **Exports + optional attestation**. -4. **CycloneDX VEX** connectors; platform claim expansion tables; UI explorer. -5. **Scale hardening**: export indexes; conflict analytics. - ---- - -## 17) Operational runbooks - -* **Statement backfill** — see `docs/dev/EXCITITOR_STATEMENT_BACKFILL.md` for the CLI workflow, required permissions, observability guidance, and rollback steps. - ---- - -## 18) Appendix — canonical JSON (stable ordering) - -All exports and consensus entries are serialized via `VexCanonicalJsonSerializer`: - -* UTF‑8 without BOM; -* keys sorted (ASCII); -* arrays sorted by `(providerId, vulnId, productKey, lastObserved)` unless semantic order mandated; -* timestamps in `YYYY‑MM‑DDThh:mm:ssZ`; -* no insignificant whitespace. - +2. **Signature policies**: PGP for distros; cosign for OCI. +3. **Exports + optional attestation**. +4. **CycloneDX VEX** connectors; platform claim expansion tables; UI explorer. +5. **Scale hardening**: export indexes; conflict analytics. + +--- + +## 18) Operational runbooks + +* **Statement backfill** — see `docs/dev/EXCITITOR_STATEMENT_BACKFILL.md` for the CLI workflow, required permissions, observability guidance, and rollback steps. + +--- + +## 19) Appendix — canonical JSON (stable ordering) + +All exports and consensus entries are serialized via `VexCanonicalJsonSerializer`: + +* UTF‑8 without BOM; +* keys sorted (ASCII); +* arrays sorted by `(providerId, vulnId, productKey, lastObserved)` unless semantic order mandated; +* timestamps in `YYYY‑MM‑DDThh:mm:ssZ`; +* no insignificant whitespace. + diff --git a/docs/modules/excititor/implementation_plan.md b/docs/modules/excititor/implementation_plan.md new file mode 100644 index 00000000..8507d0e2 --- /dev/null +++ b/docs/modules/excititor/implementation_plan.md @@ -0,0 +1,21 @@ +# Implementation plan — Excititor + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 1 – AOC enforcement:** enforce immutable VEX observation schema, provenance capture, and guardrails. +- **Epic 7 – VEX Consensus Lens:** provide lens-ready metadata (issuer trust, temporal scoping) and consensus APIs. +- **Epic 8 – Advisory AI:** guarantee citation-ready payloads and normalized context for AI summaries/explainers. +- Track DOCS-LNM-22-006/007 and CLI-EXC-25-001..002 in ../../TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ARCHITECTURE_EXCITITOR_MIRRORS.md b/docs/modules/excititor/mirrors.md similarity index 95% rename from docs/ARCHITECTURE_EXCITITOR_MIRRORS.md rename to docs/modules/excititor/mirrors.md index 06fb1e19..21421309 100644 --- a/docs/ARCHITECTURE_EXCITITOR_MIRRORS.md +++ b/docs/modules/excititor/mirrors.md @@ -1,49 +1,49 @@ -# architecture_excititor_mirrors.md — Excititor Mirror Distribution - -> **Status:** Draft (Sprint 7). Complements `docs/ARCHITECTURE_EXCITITOR.md` by describing the mirror export surface exposed by `Excititor.WebService` and the configuration hooks used by operators and downstream mirrors. - ---- - -## 0) Purpose - -Excititor publishes canonical VEX consensus data. Operators (or StellaOps-managed mirrors) need a deterministic way to sync those exports into downstream environments. Mirror distribution provides: - -* A declarative map of export bundles (`json`, `jsonl`, `openvex`, `csaf`) reachable via signed HTTP endpoints under `/excititor/mirror`. -* Thin quota/authentication controls on top of the existing export cache so mirrors cannot starve the web service. -* Stable payload shapes that downstream automation can monitor (index → fetch updates → download artifact → verify signature). - -Mirror endpoints are intentionally **read-only**. Write paths (export generation, attestation, cache) remain the responsibility of the export pipeline. - ---- - -## 1) Configuration model - -The web service reads mirror configuration from `Excititor:Mirror` (YAML/JSON/appsettings). Each domain groups a set of exports that share rate limits and authentication rules. - -```yaml -Excititor: - Mirror: - Domains: - - id: primary - displayName: Primary Mirror - requireAuthentication: false - maxIndexRequestsPerHour: 600 - maxDownloadRequestsPerHour: 1200 - exports: - - key: consensus - format: json - filters: - vulnId: CVE-2025-0001 - productKey: pkg:test/demo - sort: - createdAt: false # descending - limit: 1000 - - key: consensus-openvex - format: openvex - filters: - vulnId: CVE-2025-0001 -``` - +# architecture_excititor_mirrors.md — Excititor Mirror Distribution + +> **Status:** Draft (Sprint 7). Complements `docs/modules/excititor/architecture.md` by describing the mirror export surface exposed by `Excititor.WebService` and the configuration hooks used by operators and downstream mirrors. + +--- + +## 0) Purpose + +Excititor publishes canonical VEX consensus data. Operators (or StellaOps-managed mirrors) need a deterministic way to sync those exports into downstream environments. Mirror distribution provides: + +* A declarative map of export bundles (`json`, `jsonl`, `openvex`, `csaf`) reachable via signed HTTP endpoints under `/excititor/mirror`. +* Thin quota/authentication controls on top of the existing export cache so mirrors cannot starve the web service. +* Stable payload shapes that downstream automation can monitor (index → fetch updates → download artifact → verify signature). + +Mirror endpoints are intentionally **read-only**. Write paths (export generation, attestation, cache) remain the responsibility of the export pipeline. + +--- + +## 1) Configuration model + +The web service reads mirror configuration from `Excititor:Mirror` (YAML/JSON/appsettings). Each domain groups a set of exports that share rate limits and authentication rules. + +```yaml +Excititor: + Mirror: + Domains: + - id: primary + displayName: Primary Mirror + requireAuthentication: false + maxIndexRequestsPerHour: 600 + maxDownloadRequestsPerHour: 1200 + exports: + - key: consensus + format: json + filters: + vulnId: CVE-2025-0001 + productKey: pkg:test/demo + sort: + createdAt: false # descending + limit: 1000 + - key: consensus-openvex + format: openvex + filters: + vulnId: CVE-2025-0001 +``` + ### Root settings | Field | Required | Description | @@ -64,78 +64,78 @@ Excititor: | `keyPath` | – | Optional PEM path used to seed the provider when the key is not already loaded. | ### Domain field reference - -| Field | Required | Description | -| --- | --- | --- | -| `id` | ✅ | Stable identifier. Appears in URLs (`/excititor/mirror/domains/{id}`) and download filenames. | -| `displayName` | – | Human-friendly label surfaced in the `/domains` listing. Falls back to `id`. | -| `requireAuthentication` | – | When `true` the service enforces that the caller is authenticated (Authority token). | -| `maxIndexRequestsPerHour` | – | Per-domain quota for index endpoints. `0`/negative disables the guard. | -| `maxDownloadRequestsPerHour` | – | Per-domain quota for artifact downloads. | + +| Field | Required | Description | +| --- | --- | --- | +| `id` | ✅ | Stable identifier. Appears in URLs (`/excititor/mirror/domains/{id}`) and download filenames. | +| `displayName` | – | Human-friendly label surfaced in the `/domains` listing. Falls back to `id`. | +| `requireAuthentication` | – | When `true` the service enforces that the caller is authenticated (Authority token). | +| `maxIndexRequestsPerHour` | – | Per-domain quota for index endpoints. `0`/negative disables the guard. | +| `maxDownloadRequestsPerHour` | – | Per-domain quota for artifact downloads. | | `exports` | ✅ | Collection of export projections. | - -Export-level fields: - -| Field | Required | Description | -| --- | --- | --- | + +Export-level fields: + +| Field | Required | Description | +| --- | --- | --- | | `key` | ✅ | Unique key within the domain. Used in URLs (`/exports/{key}`) and filenames/bundle entries. | -| `format` | ✅ | One of `json`, `jsonl`, `openvex`, `csaf`. Maps to `VexExportFormat`. | -| `filters` | – | Key/value pairs executed via `VexQueryFilter`. Keys must match export data source columns (e.g., `vulnId`, `productKey`). | -| `sort` | – | Key/boolean map (false = descending). | -| `limit`, `offset`, `view` | – | Optional query bounds passed through to the export query. | - -⚠️ **Misconfiguration:** invalid formats or missing keys cause exports to be flagged with `status` in the index response; they are not exposed downstream. - ---- - -## 2) HTTP surface - -Routes are grouped under `/excititor/mirror`. - -| Method | Path | Description | -| --- | --- | --- | -| `GET` | `/domains` | Returns configured domains with quota metadata. | -| `GET` | `/domains/{domainId}` | Domain detail (auth/quota + export keys). `404` for unknown domains. | -| `GET` | `/domains/{domainId}/index` | Lists exports with exportId, query signature, format, artifact digest, attestation metadata, and size. Applies index quota. | -| `GET` | `/domains/{domainId}/exports/{exportKey}` | Returns manifest metadata (single export). `404` if unknown/missing. | -| `GET` | `/domains/{domainId}/exports/{exportKey}/download` | Streams export content from the artifact store. Applies download quota. | - -Responses are serialized via `VexCanonicalJsonSerializer` ensuring stable ordering. Download responses include a content-disposition header naming the file `-.`. - -### Error handling - -* `401` – authentication required (`requireAuthentication=true`). -* `404` – domain/export not found or manifest not persisted. -* `429` – per-domain quota exceeded (`Retry-After` header set in seconds). -* `503` – export misconfiguration (invalid format/query). - ---- - -## 3) Rate limiting - -`MirrorRateLimiter` implements a simple rolling 1-hour window using `IMemoryCache`. Each domain has two quotas: - -* `index` scope → `maxIndexRequestsPerHour` -* `download` scope → `maxDownloadRequestsPerHour` - -`0` or negative limits disable enforcement. Quotas are best-effort (per-instance). For HA deployments, configure sticky routing at the ingress or replace the limiter with a distributed implementation. - ---- - -## 4) Interaction with export pipeline - -Mirror endpoints consume manifests produced by the export engine (`MongoVexExportStore`). They do **not** trigger new exports. Operators must configure connectors/exporters to keep targeted exports fresh (see `EXCITITOR-EXPORT-01-005/006/007`). - -Recommended workflow: - -1. Define export plans at the export layer (JSON/OpenVEX/CSAF). -2. Configure mirror domains mapping to those plans. -3. Downstream mirror automation: - * `GET /domains/{id}/index` - * Compare `exportId` / `consensusRevision` - * `GET /download` when new - * Verify digest + attestation - +| `format` | ✅ | One of `json`, `jsonl`, `openvex`, `csaf`. Maps to `VexExportFormat`. | +| `filters` | – | Key/value pairs executed via `VexQueryFilter`. Keys must match export data source columns (e.g., `vulnId`, `productKey`). | +| `sort` | – | Key/boolean map (false = descending). | +| `limit`, `offset`, `view` | – | Optional query bounds passed through to the export query. | + +⚠️ **Misconfiguration:** invalid formats or missing keys cause exports to be flagged with `status` in the index response; they are not exposed downstream. + +--- + +## 2) HTTP surface + +Routes are grouped under `/excititor/mirror`. + +| Method | Path | Description | +| --- | --- | --- | +| `GET` | `/domains` | Returns configured domains with quota metadata. | +| `GET` | `/domains/{domainId}` | Domain detail (auth/quota + export keys). `404` for unknown domains. | +| `GET` | `/domains/{domainId}/index` | Lists exports with exportId, query signature, format, artifact digest, attestation metadata, and size. Applies index quota. | +| `GET` | `/domains/{domainId}/exports/{exportKey}` | Returns manifest metadata (single export). `404` if unknown/missing. | +| `GET` | `/domains/{domainId}/exports/{exportKey}/download` | Streams export content from the artifact store. Applies download quota. | + +Responses are serialized via `VexCanonicalJsonSerializer` ensuring stable ordering. Download responses include a content-disposition header naming the file `-.`. + +### Error handling + +* `401` – authentication required (`requireAuthentication=true`). +* `404` – domain/export not found or manifest not persisted. +* `429` – per-domain quota exceeded (`Retry-After` header set in seconds). +* `503` – export misconfiguration (invalid format/query). + +--- + +## 3) Rate limiting + +`MirrorRateLimiter` implements a simple rolling 1-hour window using `IMemoryCache`. Each domain has two quotas: + +* `index` scope → `maxIndexRequestsPerHour` +* `download` scope → `maxDownloadRequestsPerHour` + +`0` or negative limits disable enforcement. Quotas are best-effort (per-instance). For HA deployments, configure sticky routing at the ingress or replace the limiter with a distributed implementation. + +--- + +## 4) Interaction with export pipeline + +Mirror endpoints consume manifests produced by the export engine (`MongoVexExportStore`). They do **not** trigger new exports. Operators must configure connectors/exporters to keep targeted exports fresh (see `EXCITITOR-EXPORT-01-005/006/007`). + +Recommended workflow: + +1. Define export plans at the export layer (JSON/OpenVEX/CSAF). +2. Configure mirror domains mapping to those plans. +3. Downstream mirror automation: + * `GET /domains/{id}/index` + * Compare `exportId` / `consensusRevision` + * `GET /download` when new + * Verify digest + attestation + When the export engine runs, it materializes the following artefacts under `outputRoot/`: - `index.json` – canonical index listing each configured domain, manifest/bundle descriptors (with SHA-256 digests), and available export keys. @@ -144,21 +144,21 @@ When the export engine runs, it materializes the following artefacts under `outp - `/bundle.json.jws` – optional detached JWS when signing is enabled. Downstream automation reads `manifest.json`/`bundle.json` directly, while `/excititor/mirror` endpoints stream the same artefacts through authenticated HTTP. - ---- - -## 5) Operational guidance - -* Track quota utilisation via HTTP 429 metrics (configure structured logging or OTEL counters when rate limiting triggers). -* Mirror domains can be deployed per tenant (e.g., `tenant-a`, `tenant-b`) with different auth requirements. -* Ensure the underlying artifact stores (`FileSystem`, `S3`, offline bundle) retain artefacts long enough for mirrors to sync. -* For air-gapped mirrors, combine mirror endpoints with the Offline Kit (see `docs/24_OFFLINE_KIT.md`). - ---- - -## 6) Future alignment - -* Replace manual export definitions with generated mirror bundle manifests once `EXCITITOR-EXPORT-01-007` ships. -* Extend `/index` payload with quiet-provenance when `EXCITITOR-EXPORT-01-006` adds that metadata. -* Integrate domain manifests with DevOps mirror profiles (`DEVOPS-MIRROR-08-001`) so helm/compose overlays can enable or disable domains declaratively. - + +--- + +## 5) Operational guidance + +* Track quota utilisation via HTTP 429 metrics (configure structured logging or OTEL counters when rate limiting triggers). +* Mirror domains can be deployed per tenant (e.g., `tenant-a`, `tenant-b`) with different auth requirements. +* Ensure the underlying artifact stores (`FileSystem`, `S3`, offline bundle) retain artefacts long enough for mirrors to sync. +* For air-gapped mirrors, combine mirror endpoints with the Offline Kit (see `docs/24_OFFLINE_KIT.md`). + +--- + +## 6) Future alignment + +* Replace manual export definitions with generated mirror bundle manifests once `EXCITITOR-EXPORT-01-007` ships. +* Extend `/index` payload with quiet-provenance when `EXCITITOR-EXPORT-01-006` adds that metadata. +* Integrate domain manifests with DevOps mirror profiles (`DEVOPS-MIRROR-08-001`) so helm/compose overlays can enable or disable domains declaratively. + diff --git a/docs/EXCITITOR_SCORRING.md b/docs/modules/excititor/scoring.md similarity index 100% rename from docs/EXCITITOR_SCORRING.md rename to docs/modules/excititor/scoring.md diff --git a/docs/modules/export-center/AGENTS.md b/docs/modules/export-center/AGENTS.md new file mode 100644 index 00000000..a6b7906e --- /dev/null +++ b/docs/modules/export-center/AGENTS.md @@ -0,0 +1,22 @@ +# Export Center agent guide + +## Mission +Export Center packages reproducible evidence bundles (JSON, Trivy DB, mirror) with provenance metadata and optional signing for offline or mirrored deployments. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/export-center/README.md b/docs/modules/export-center/README.md new file mode 100644 index 00000000..23b24871 --- /dev/null +++ b/docs/modules/export-center/README.md @@ -0,0 +1,34 @@ +# StellaOps Export Center + +Export Center packages reproducible evidence bundles (JSON, Trivy DB, mirror) with provenance metadata and optional signing for offline or mirrored deployments. + +## Responsibilities +- Coordinate export jobs based on profiles and scope selectors. +- Assemble manifests, provenance documents, and cosign signatures. +- Stream bundles via HTTP/OCI and stage them for Offline Kit uses. +- Expose CLI/API surfaces for automation. + +## Key components +- `StellaOps.ExportCenter.WebService` planner. +- `StellaOps.ExportCenter.Worker` bundle builder. +- Adapters in `StellaOps.ExportCenter.*` for JSON/Trivy/mirror variants. + +## Integrations & dependencies +- Concelier/Excititor/Policy data stores for evidence. +- Signer/Attestor for provenance signing. +- CLI for operator-managed exports. + +## Operational notes +- Runbooks in ./operations/ for deployment and monitoring. +- Mirror bundle instructions and validation notes. +- Telemetry dashboards for export latency and retry rates. + +## Related resources +- ./operations/runbook.md + +## Backlog references +- DOCS-EXPORT-35-001 … DOCS-EXPORT-37-002 in ../../TASKS.md. +- EXPORT-ATTEST-75-002 cross-team deliverable. + +## Epic alignment +- **Epic 10 – Export Center:** deliver canonical JSON, Trivy DB, and mirror bundle workflows with provenance, signatures, and offline parity. diff --git a/docs/modules/export-center/TASKS.md b/docs/modules/export-center/TASKS.md new file mode 100644 index 00000000..a717d87b --- /dev/null +++ b/docs/modules/export-center/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Export Center + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| EXPORT CENTER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| EXPORT CENTER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| EXPORT CENTER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/export-center/api.md b/docs/modules/export-center/api.md similarity index 96% rename from docs/export-center/api.md rename to docs/modules/export-center/api.md index 838744e6..b4222d26 100644 --- a/docs/export-center/api.md +++ b/docs/modules/export-center/api.md @@ -1,337 +1,337 @@ -# Export Center REST API - -> **Audience:** Platform integrators, Console/CLI developers, and automation engineers orchestrating export runs. -> **Base route:** `/api/export/*` behind the StellaOps gateway; requires Authority-issued tokens with export scopes. - -This reference describes the Export Center API introduced in Export Center Phase 1 (Epic 10) and extended in Phase 2. Use it alongside the [Export Center Architecture](architecture.md) and [Profiles](profiles.md) guides for service-level semantics. - -> Status: Endpoint implementation lands with `EXPORT-SVC-35-006` (Sprint 35) and related follow-on tasks. As of the current build the WebService hosts only the template stub; use this contract for coordination and update once the API is wired. - -## 1. Authentication and headers - -- **Authorization:** Bearer tokens in `Authorization: Bearer ` paired with DPoP proof. Required scopes per endpoint: - - `export:profile:manage` for profile CRUD. - - `export:run` to submit and cancel runs. - - `export:read` to list and inspect runs. - - `export:download` for bundle downloads and manifests. -- **Tenant context:** Provide `X-Stella-Tenant` when the token carries multiple tenants; defaults to token tenant otherwise. -- **Idempotency:** Mutating endpoints accept `Idempotency-Key` (UUID). Retrying with the same key returns the original result. -- **Rate limits and quotas:** Responses include `X-Stella-Quota-Limit`, `X-Stella-Quota-Remaining`, and `X-Stella-Quota-Reset`. Exceeding quotas returns `429 Too Many Requests` with `ERR_EXPORT_QUOTA`. -- **Content negotiation:** Requests and responses use `application/json; charset=utf-8` unless otherwise stated. Downloads stream binary content with profile-specific media types. -- **SSE:** Event streams set `Content-Type: text/event-stream` and keep connections alive with comment heartbeats every 15 seconds. - -## 2. Error model - -Errors follow standard HTTP codes with structured payloads: - -```json -{ - "code": "ERR_EXPORT_002", - "message": "Profile not found for tenant acme", - "details": [], - "traceId": "01J9N4Y4K2XY8C5V7T2S", - "timestamp": "2025-10-29T13:42:11Z" -} -``` - -| Code | Description | Typical HTTP status | Notes | -|------|-------------|---------------------|-------| -| `ERR_EXPORT_001` | Validation failure (selectors, configuration) | 400 | `details` enumerates offending fields. | -| `ERR_EXPORT_002` | Profile missing or not accessible for tenant | 404 | Returned on run submission or profile fetch. | -| `ERR_EXPORT_003` | Concurrency or quota exceeded | 429 | Includes `retryAfterSeconds` in `details`. | -| `ERR_EXPORT_004` | Adapter failure (schema mismatch, upstream outage) | 502 | Worker logs contain adapter error reason. | -| `ERR_EXPORT_005` | Signing or KMS error | 500 | Run marked failed with `errorCode=signing`. | -| `ERR_EXPORT_006` | Distribution failure (HTTP, OCI, object storage) | 502 | `details` lists failing distribution driver. | -| `ERR_EXPORT_007` | Run canceled or expired | 409 | Includes cancel author and timestamp. | -| `ERR_EXPORT_BASE_MISSING` | Base manifest for delta exports not found | 400 | Specific to `mirror:delta`. | -| `ERR_EXPORT_EMPTY` | No records matched selectors (when `allowEmpty=false`) | 422 | Useful for guard-railled automation. | -| `ERR_EXPORT_QUOTA` | Daily quota exhausted | 429 | Always paired with quota headers. | - -All responses include `traceId` for correlation with logs and metrics. - -## 3. Profiles endpoints - -### 3.1 List profiles - -``` -GET /api/export/profiles?kind=json&variant=raw&page=1&pageSize=20 -Scopes: export:read -``` - -Returns tenant-scoped profiles. Response headers: `X-Total-Count`, `Link` for pagination. - -**Response** - -```json -{ - "items": [ - { - "profileId": "prof-json-raw", - "name": "Daily JSON Raw", - "kind": "json", - "variant": "raw", - "distribution": ["http", "object"], - "retention": {"mode": "days", "value": 14}, - "createdAt": "2025-10-23T08:00:00Z", - "createdBy": "user:ops" - } - ], - "page": 1, - "pageSize": 20 -} -``` - -### 3.2 Get a profile - -``` -GET /api/export/profiles/{profileId} -Scopes: export:read -``` - -Returns full configuration, including `config` payload, distribution options, and metadata. - -### 3.3 Create a profile - -``` -POST /api/export/profiles -Scopes: export:profile:manage -``` - -**Request** - -```json -{ - "profileId": "prof-airgap-mirror", - "name": "Airgap Mirror Weekly", - "kind": "mirror", - "variant": "full", - "include": ["advisories", "vex", "sboms", "policy"], - "distribution": ["http", "object"], - "encryption": { - "enabled": true, - "recipientKeys": ["age1tenantkey..."], - "strict": false - }, - "retention": {"mode": "days", "value": 30} -} -``` - -**Response 201** - -```json -{ - "profileId": "prof-airgap-mirror", - "version": 1, - "createdAt": "2025-10-29T12:05:22Z", - "createdBy": "user:ops", - "status": "active" -} -``` - -### 3.4 Update profile metadata - -``` -PATCH /api/export/profiles/{profileId} -Scopes: export:profile:manage -``` - -Allows renaming, toggling distribution switches, or updating retention. Structural configuration updates (kind/variant/include) create a new revision; the API returns `revisionCreated=true` and the new `profileId` (e.g., `prof-airgap-mirror@2`). - -### 3.5 Archive profile - -``` -POST /api/export/profiles/{profileId}:archive -Scopes: export:profile:manage -``` - -Marks profile as inactive; existing runs remain accessible. Use `:restore` to reactivate. - -## 4. Run management - -### 4.1 Submit an export run - -``` -POST /api/export/runs -Scopes: export:run -``` - -**Request** - -```json -{ - "profileId": "prof-json-raw", - "selectors": { - "tenants": ["acme"], - "timeWindow": { - "from": "2025-10-01T00:00:00Z", - "to": "2025-10-29T00:00:00Z" - }, - "products": ["registry.example.com/app:*"], - "sboms": ["sbom:S-1001", "sbom:S-2004"] - }, - "policySnapshotId": "policy-snap-42", - "options": { - "allowEmpty": false, - "priority": "standard" - } -} -``` - -**Response 202** - -```json -{ - "runId": "run-20251029-01", - "status": "pending", - "profileId": "prof-json-raw", - "createdAt": "2025-10-29T12:12:11Z", - "createdBy": "user:ops", - "selectors": { "...": "..." }, - "links": { - "self": "/api/export/runs/run-20251029-01", - "events": "/api/export/runs/run-20251029-01/events" - } -} -``` - -### 4.2 List runs - -``` -GET /api/export/runs?status=active&profileId=prof-json-raw&page=1&pageSize=10 -Scopes: export:read -``` - -Returns latest runs with pagination. Each item includes summary counts, duration, and last event. - -### 4.3 Get run status - -``` -GET /api/export/runs/{runId} -Scopes: export:read -``` - -Response fields: - -| Field | Description | -|-------|-------------| -| `status` | `pending`, `running`, `success`, `failed`, `canceled`. | -| `progress` | Object with `adapters`, `bytesWritten`, `recordsProcessed`. | -| `errorCode` | Populated when `status=failed` (`signing`, `distribution`, etc). | -| `policySnapshotId` | Returned for policy-aware profiles. | -| `distributions` | List of available distribution descriptors (type, location, sha256, expiresAt). | - -### 4.4 Cancel a run - -``` -POST /api/export/runs/{runId}:cancel -Scopes: export:run -``` - -Body optional (`{"reason": "Aborted due to incident INC-123"}`). Returns 202 and pushes `run.canceled` event. - -## 5. Events and telemetry - -### 5.1 Server-sent events - -``` -GET /api/export/runs/{runId}/events -Scopes: export:read -Accept: text/event-stream -``` - -Event payload example: - -``` -event: run.progress -data: {"runId":"run-20251029-01","phase":"adapter","adapter":"json","records":1024,"bytes":7340032,"timestamp":"2025-10-29T12:13:15Z"} -``` - -Event types: - -| Event | Meaning | -|-------|---------| -| `run.accepted` | Planner accepted job and queued with Orchestrator. | -| `run.progress` | Periodic updates with phase, adapter, counts. | -| `run.distribution` | Distribution driver finished (includes descriptor). | -| `run.signed` | Signing completed successfully. | -| `run.succeeded` | Run marked `success`. | -| `run.failed` | Run failed; payload includes `errorCode`. | -| `run.canceled` | Run canceled; includes `canceledBy`. | - -SSE heartbeats (`: ping`) keep long-lived connections alive and should be ignored by clients. - -### 5.2 Audit events - -`GET /api/export/runs/{runId}/events?format=audit` returns the same event stream in newline-delimited JSON for offline ingestion. - -## 6. Download endpoints - -### 6.1 Bundle download - -``` -GET /api/export/runs/{runId}/download -Scopes: export:download -``` - -Streams the primary bundle (tarball, zip, or profile-specific layout). Headers: - -- `Content-Disposition: attachment; filename="export-run-20251029-01.tar.zst"` -- `X-Export-Digest: sha256:...` -- `X-Export-Size: 73482019` -- `X-Export-Encryption: age` (when mirror encryption enabled) - -Supports HTTP range requests for resume functionality. If no bundle exists yet, responds `409` with `ERR_EXPORT_007`. - -### 6.2 Manifest download - -``` -GET /api/export/runs/{runId}/manifest -Scopes: export:download -``` - -Returns signed `export.json`. To fetch the detached signature, append `?signature=true`. - -### 6.3 Provenance download - -``` -GET /api/export/runs/{runId}/provenance -Scopes: export:download -``` - -Returns signed `provenance.json`. Supports `?signature=true`. Provenance includes attestation subject digests, policy snapshot ids, adapter versions, and KMS key identifiers. - -### 6.4 Distribution descriptors - -``` -GET /api/export/runs/{runId}/distributions -Scopes: export:read -``` - -Lists all registered distribution targets (HTTP, OCI, object storage). Each item includes `type`, `location`, `sha256`, `sizeBytes`, and `expiresAt`. - -## 7. Webhook hand-off - -Exports can notify external systems once a run succeeds by registering an HTTP webhook: - -``` -POST /api/export/webhooks -Scopes: export:profile:manage -``` - -Payload includes `targetUrl`, `events` (e.g., `run.succeeded`), and optional secret for HMAC signatures. Webhook deliveries sign payloads with `X-Stella-Signature` header (`sha256=...`). Retries follow exponential backoff with dead-letter capture in `export_events`. - -## 8. Observability - -- **Metrics endpoint:** `/metrics` (service-local) exposes Prometheus metrics listed in [Architecture](architecture.md#observability). -- **Tracing:** When `traceparent` header is provided, worker spans join the calling trace. -- **Run lookup by trace:** Use `GET /api/export/runs?traceId={id}` when troubleshooting distributed traces. - -## 9. Related documentation - -- [Export Center Overview](overview.md) -- [Export Center Architecture](architecture.md) -- [Export Center Profiles](profiles.md) -- [Export Center CLI Guide](cli.md) *(companion document)* -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center REST API + +> **Audience:** Platform integrators, Console/CLI developers, and automation engineers orchestrating export runs. +> **Base route:** `/api/export/*` behind the StellaOps gateway; requires Authority-issued tokens with export scopes. + +This reference describes the Export Center API introduced in Export Center Phase 1 (Epic 10) and extended in Phase 2. Use it alongside the [Export Center Architecture](architecture.md) and [Profiles](profiles.md) guides for service-level semantics. + +> Status: Endpoint implementation lands with `EXPORT-SVC-35-006` (Sprint 35) and related follow-on tasks. As of the current build the WebService hosts only the template stub; use this contract for coordination and update once the API is wired. + +## 1. Authentication and headers + +- **Authorization:** Bearer tokens in `Authorization: Bearer ` paired with DPoP proof. Required scopes per endpoint: + - `export:profile:manage` for profile CRUD. + - `export:run` to submit and cancel runs. + - `export:read` to list and inspect runs. + - `export:download` for bundle downloads and manifests. +- **Tenant context:** Provide `X-Stella-Tenant` when the token carries multiple tenants; defaults to token tenant otherwise. +- **Idempotency:** Mutating endpoints accept `Idempotency-Key` (UUID). Retrying with the same key returns the original result. +- **Rate limits and quotas:** Responses include `X-Stella-Quota-Limit`, `X-Stella-Quota-Remaining`, and `X-Stella-Quota-Reset`. Exceeding quotas returns `429 Too Many Requests` with `ERR_EXPORT_QUOTA`. +- **Content negotiation:** Requests and responses use `application/json; charset=utf-8` unless otherwise stated. Downloads stream binary content with profile-specific media types. +- **SSE:** Event streams set `Content-Type: text/event-stream` and keep connections alive with comment heartbeats every 15 seconds. + +## 2. Error model + +Errors follow standard HTTP codes with structured payloads: + +```json +{ + "code": "ERR_EXPORT_002", + "message": "Profile not found for tenant acme", + "details": [], + "traceId": "01J9N4Y4K2XY8C5V7T2S", + "timestamp": "2025-10-29T13:42:11Z" +} +``` + +| Code | Description | Typical HTTP status | Notes | +|------|-------------|---------------------|-------| +| `ERR_EXPORT_001` | Validation failure (selectors, configuration) | 400 | `details` enumerates offending fields. | +| `ERR_EXPORT_002` | Profile missing or not accessible for tenant | 404 | Returned on run submission or profile fetch. | +| `ERR_EXPORT_003` | Concurrency or quota exceeded | 429 | Includes `retryAfterSeconds` in `details`. | +| `ERR_EXPORT_004` | Adapter failure (schema mismatch, upstream outage) | 502 | Worker logs contain adapter error reason. | +| `ERR_EXPORT_005` | Signing or KMS error | 500 | Run marked failed with `errorCode=signing`. | +| `ERR_EXPORT_006` | Distribution failure (HTTP, OCI, object storage) | 502 | `details` lists failing distribution driver. | +| `ERR_EXPORT_007` | Run canceled or expired | 409 | Includes cancel author and timestamp. | +| `ERR_EXPORT_BASE_MISSING` | Base manifest for delta exports not found | 400 | Specific to `mirror:delta`. | +| `ERR_EXPORT_EMPTY` | No records matched selectors (when `allowEmpty=false`) | 422 | Useful for guard-railled automation. | +| `ERR_EXPORT_QUOTA` | Daily quota exhausted | 429 | Always paired with quota headers. | + +All responses include `traceId` for correlation with logs and metrics. + +## 3. Profiles endpoints + +### 3.1 List profiles + +``` +GET /api/export/profiles?kind=json&variant=raw&page=1&pageSize=20 +Scopes: export:read +``` + +Returns tenant-scoped profiles. Response headers: `X-Total-Count`, `Link` for pagination. + +**Response** + +```json +{ + "items": [ + { + "profileId": "prof-json-raw", + "name": "Daily JSON Raw", + "kind": "json", + "variant": "raw", + "distribution": ["http", "object"], + "retention": {"mode": "days", "value": 14}, + "createdAt": "2025-10-23T08:00:00Z", + "createdBy": "user:ops" + } + ], + "page": 1, + "pageSize": 20 +} +``` + +### 3.2 Get a profile + +``` +GET /api/export/profiles/{profileId} +Scopes: export:read +``` + +Returns full configuration, including `config` payload, distribution options, and metadata. + +### 3.3 Create a profile + +``` +POST /api/export/profiles +Scopes: export:profile:manage +``` + +**Request** + +```json +{ + "profileId": "prof-airgap-mirror", + "name": "Airgap Mirror Weekly", + "kind": "mirror", + "variant": "full", + "include": ["advisories", "vex", "sboms", "policy"], + "distribution": ["http", "object"], + "encryption": { + "enabled": true, + "recipientKeys": ["age1tenantkey..."], + "strict": false + }, + "retention": {"mode": "days", "value": 30} +} +``` + +**Response 201** + +```json +{ + "profileId": "prof-airgap-mirror", + "version": 1, + "createdAt": "2025-10-29T12:05:22Z", + "createdBy": "user:ops", + "status": "active" +} +``` + +### 3.4 Update profile metadata + +``` +PATCH /api/export/profiles/{profileId} +Scopes: export:profile:manage +``` + +Allows renaming, toggling distribution switches, or updating retention. Structural configuration updates (kind/variant/include) create a new revision; the API returns `revisionCreated=true` and the new `profileId` (e.g., `prof-airgap-mirror@2`). + +### 3.5 Archive profile + +``` +POST /api/export/profiles/{profileId}:archive +Scopes: export:profile:manage +``` + +Marks profile as inactive; existing runs remain accessible. Use `:restore` to reactivate. + +## 4. Run management + +### 4.1 Submit an export run + +``` +POST /api/export/runs +Scopes: export:run +``` + +**Request** + +```json +{ + "profileId": "prof-json-raw", + "selectors": { + "tenants": ["acme"], + "timeWindow": { + "from": "2025-10-01T00:00:00Z", + "to": "2025-10-29T00:00:00Z" + }, + "products": ["registry.example.com/app:*"], + "sboms": ["sbom:S-1001", "sbom:S-2004"] + }, + "policySnapshotId": "policy-snap-42", + "options": { + "allowEmpty": false, + "priority": "standard" + } +} +``` + +**Response 202** + +```json +{ + "runId": "run-20251029-01", + "status": "pending", + "profileId": "prof-json-raw", + "createdAt": "2025-10-29T12:12:11Z", + "createdBy": "user:ops", + "selectors": { "...": "..." }, + "links": { + "self": "/api/export/runs/run-20251029-01", + "events": "/api/export/runs/run-20251029-01/events" + } +} +``` + +### 4.2 List runs + +``` +GET /api/export/runs?status=active&profileId=prof-json-raw&page=1&pageSize=10 +Scopes: export:read +``` + +Returns latest runs with pagination. Each item includes summary counts, duration, and last event. + +### 4.3 Get run status + +``` +GET /api/export/runs/{runId} +Scopes: export:read +``` + +Response fields: + +| Field | Description | +|-------|-------------| +| `status` | `pending`, `running`, `success`, `failed`, `canceled`. | +| `progress` | Object with `adapters`, `bytesWritten`, `recordsProcessed`. | +| `errorCode` | Populated when `status=failed` (`signing`, `distribution`, etc). | +| `policySnapshotId` | Returned for policy-aware profiles. | +| `distributions` | List of available distribution descriptors (type, location, sha256, expiresAt). | + +### 4.4 Cancel a run + +``` +POST /api/export/runs/{runId}:cancel +Scopes: export:run +``` + +Body optional (`{"reason": "Aborted due to incident INC-123"}`). Returns 202 and pushes `run.canceled` event. + +## 5. Events and telemetry + +### 5.1 Server-sent events + +``` +GET /api/export/runs/{runId}/events +Scopes: export:read +Accept: text/event-stream +``` + +Event payload example: + +``` +event: run.progress +data: {"runId":"run-20251029-01","phase":"adapter","adapter":"json","records":1024,"bytes":7340032,"timestamp":"2025-10-29T12:13:15Z"} +``` + +Event types: + +| Event | Meaning | +|-------|---------| +| `run.accepted` | Planner accepted job and queued with Orchestrator. | +| `run.progress` | Periodic updates with phase, adapter, counts. | +| `run.distribution` | Distribution driver finished (includes descriptor). | +| `run.signed` | Signing completed successfully. | +| `run.succeeded` | Run marked `success`. | +| `run.failed` | Run failed; payload includes `errorCode`. | +| `run.canceled` | Run canceled; includes `canceledBy`. | + +SSE heartbeats (`: ping`) keep long-lived connections alive and should be ignored by clients. + +### 5.2 Audit events + +`GET /api/export/runs/{runId}/events?format=audit` returns the same event stream in newline-delimited JSON for offline ingestion. + +## 6. Download endpoints + +### 6.1 Bundle download + +``` +GET /api/export/runs/{runId}/download +Scopes: export:download +``` + +Streams the primary bundle (tarball, zip, or profile-specific layout). Headers: + +- `Content-Disposition: attachment; filename="export-run-20251029-01.tar.zst"` +- `X-Export-Digest: sha256:...` +- `X-Export-Size: 73482019` +- `X-Export-Encryption: age` (when mirror encryption enabled) + +Supports HTTP range requests for resume functionality. If no bundle exists yet, responds `409` with `ERR_EXPORT_007`. + +### 6.2 Manifest download + +``` +GET /api/export/runs/{runId}/manifest +Scopes: export:download +``` + +Returns signed `export.json`. To fetch the detached signature, append `?signature=true`. + +### 6.3 Provenance download + +``` +GET /api/export/runs/{runId}/provenance +Scopes: export:download +``` + +Returns signed `provenance.json`. Supports `?signature=true`. Provenance includes attestation subject digests, policy snapshot ids, adapter versions, and KMS key identifiers. + +### 6.4 Distribution descriptors + +``` +GET /api/export/runs/{runId}/distributions +Scopes: export:read +``` + +Lists all registered distribution targets (HTTP, OCI, object storage). Each item includes `type`, `location`, `sha256`, `sizeBytes`, and `expiresAt`. + +## 7. Webhook hand-off + +Exports can notify external systems once a run succeeds by registering an HTTP webhook: + +``` +POST /api/export/webhooks +Scopes: export:profile:manage +``` + +Payload includes `targetUrl`, `events` (e.g., `run.succeeded`), and optional secret for HMAC signatures. Webhook deliveries sign payloads with `X-Stella-Signature` header (`sha256=...`). Retries follow exponential backoff with dead-letter capture in `export_events`. + +## 8. Observability + +- **Metrics endpoint:** `/metrics` (service-local) exposes Prometheus metrics listed in [Architecture](architecture.md#observability). +- **Tracing:** When `traceparent` header is provided, worker spans join the calling trace. +- **Run lookup by trace:** Use `GET /api/export/runs?traceId={id}` when troubleshooting distributed traces. + +## 9. Related documentation + +- [Export Center Overview](overview.md) +- [Export Center Architecture](architecture.md) +- [Export Center Profiles](profiles.md) +- [Export Center CLI Guide](cli.md) *(companion document)* +- [Aggregation-Only Contract reference](../../ingestion/aggregation-only-contract.md) + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/export-center/architecture.md b/docs/modules/export-center/architecture.md similarity index 97% rename from docs/export-center/architecture.md rename to docs/modules/export-center/architecture.md index 7775250d..fca31911 100644 --- a/docs/export-center/architecture.md +++ b/docs/modules/export-center/architecture.md @@ -1,125 +1,127 @@ -# Export Center Architecture - -The Export Center is the dedicated service layer that packages StellaOps evidence and policy overlays into reproducible bundles. It runs as a multi-surface API backed by asynchronous workers and format adapters, enforcing Aggregation-Only Contract (AOC) guardrails while providing deterministic manifests, signing, and distribution paths. - -## Runtime topology -- **Export Center API (`StellaOps.ExportCenter.WebService`).** Receives profile CRUD, export run requests, status queries, and download streams through the unified Web API gateway. Enforces tenant scopes, RBAC, quotas, and concurrency guards. -- **Export Center Worker (`StellaOps.ExportCenter.Worker`).** Dequeues export jobs from the Orchestrator, resolves selectors, invokes adapters, and writes manifests and bundle artefacts. Stateless; scales horizontally. -- **Backing stores.** - - MongoDB collections: `export_profiles`, `export_runs`, `export_inputs`, `export_distributions`, `export_events`. - - Object storage bucket or filesystem for staging bundle payloads. - - Optional registry/object storage credentials injected via Authority-scoped secrets. -- **Integration peers.** - - **Findings Ledger** for advisory, VEX, SBOM payload streaming. - - **Policy Engine** for deterministic policy snapshots and evaluated findings. - - **Orchestrator** for job scheduling, quotas, and telemetry fan-out. - - **Authority** for tenant-aware access tokens and KMS key references. - - **Console & CLI** as presentation surfaces consuming the API. - -## Job lifecycle -1. **Profile selection.** Operator or automation picks a profile (`json:raw`, `json:policy`, `trivy:db`, `trivy:java-db`, `mirror:full`, `mirror:delta`) and submits scope selectors (tenant, time window, products, SBOM subjects, ecosystems). See `docs/export-center/profiles.md` for profile definitions and configuration fields. -2. **Planner resolution.** API validates selectors, expands include/exclude lists, and writes a pending `export_run` with immutable parameters and deterministic ordering hints. -3. **Orchestrator dispatch.** `export_run` triggers a job lease via Orchestrator with quotas per tenant/profile and concurrency caps (default 4 active per tenant). -4. **Worker execution.** Worker streams data from Findings Ledger and Policy Engine using pagination cursors. Adapters write canonical payloads to staging storage, compute checksums, and emit streaming progress events (SSE). -5. **Manifest and provenance emission.** Worker writes `export.json` and `provenance.json`, signs them with configured KMS keys (cosign-compatible), and uploads signatures alongside content. -6. **Distribution registration.** Worker records available distribution methods (download URL, OCI reference, object storage path), raises completion/failure events, and exposes metrics/logs. -7. **Download & verification.** Clients download bundles or pull OCI artefacts, verify signatures, and consume provenance to trace source artefacts. - -Cancellation requests mark runs as `aborted` and cause workers to stop iterating sources; partially written files are destroyed and the run is marked with an audit entry. - -## Core components -### API surface -- Detailed request and response payloads are catalogued in `docs/export-center/api.md`. -- **Profiles API.** - - `GET /api/export/profiles`: list tenant-scoped profiles. - - `POST /api/export/profiles`: create custom profiles (variants of JSON, Trivy, mirror) with validated configuration schema. - - `PATCH /api/export/profiles/{id}`: update metadata; config changes clone new revision to preserve determinism. -- **Runs API.** - - `POST /api/export/runs`: submit export run for a profile with selectors and options (policy snapshot id, mirror base manifest). - - `GET /api/export/runs/{id}`: status, progress counters, provenance summary. - - `GET /api/export/runs/{id}/events`: server-sent events with state transitions, adapter milestones, signing status. - - `POST /api/export/runs/{id}/cancel`: cooperative cancellation with audit logging. -- **Downloads API.** - - `GET /api/export/runs/{id}/download`: streaming download with range support and checksum trailers. - - `GET /api/export/runs/{id}/manifest`: signed `export.json`. - - `GET /api/export/runs/{id}/provenance`: signed `provenance.json`. - -All endpoints require Authority-issued JWT + DPoP tokens with scopes `export:run`, `export:read`, and tenant claim alignment. Rate-limiting and quotas surface via `X-Stella-Quota-*` headers. - -### Worker pipeline -- **Input resolvers.** Query Findings Ledger and Policy Engine using stable pagination (Mongo `_id` ascending, or resume tokens for change streams). Selector expressions compile into Mongo filter fragments and/or API query parameters. -- **Adapter host.** Adapter plugin loader (restart-time only) resolves profile variant to adapter implementation. Adapters present a deterministic `RunAsync(context)` contract with streaming writers and telemetry instrumentation. -- **Content writers.** - - JSON adapters emit `.jsonl.zst` files with canonical ordering (tenant, subject, document id). - - Trivy adapters materialise SQLite databases or tar archives matching Trivy DB expectations; schema version gates prevent unsupported outputs. - - Mirror adapters assemble deterministic filesystem trees (manifests, indexes, payload subtrees) and, when configured, OCI artefact layers. -- **Manifest generator.** Aggregates counts, bytes, hash digests (SHA-256), profile metadata, and input references. Writes `export.json` and `provenance.json` using canonical JSON (sorted keys, RFC3339 UTC timestamps). -- **Signing service.** Integrates with platform KMS via Authority (default cosign signer). Produces in-toto SLSA attestations when configured. Supports detached signatures and optional in-bundle signatures. -- **Distribution drivers.** `dist-http` exposes staged files via download endpoint; `dist-oci` pushes artefacts to registries using ORAS with digest pinning; `dist-objstore` uploads to tenant-specific prefixes with immutability flags. - -## Data model snapshots - -| Collection | Purpose | Key fields | Notes | -|------------|---------|------------|-------| -| `export_profiles` | Profile definitions (kind, variant, config). | `_id`, `tenant`, `name`, `kind`, `variant`, `config_json`, `created_by`, `created_at`. | Config includes adapter parameters (included record types, compression, encryption). | -| `export_runs` | Run state machine and audit info. | `_id`, `profile_id`, `tenant`, `status`, `requested_by`, `selectors`, `policy_snapshot_id`, `started_at`, `completed_at`, `duration_ms`, `error_code`. | Immutable selectors; status transitions recorded in `export_events`. | -| `export_inputs` | Resolved input ranges. | `run_id`, `source`, `cursor`, `count`, `hash`. | Enables resumable retries and audit. | -| `export_distributions` | Distribution artefacts. | `run_id`, `type` (`http`, `oci`, `object`), `location`, `sha256`, `size_bytes`, `expires_at`. | `expires_at` used for retention policies and automatic pruning. | -| `export_events` | Timeline of state transitions and metrics. | `run_id`, `event_type`, `message`, `at`, `metrics`. | Feeds SSE stream and audit trails. | - -## Adapter responsibilities -- **JSON (`json:raw`, `json:policy`).** - - Ensures canonical casing, timezone normalization, and linkset preservation. - - Policy variant embeds policy snapshot metadata (`policy_version`, `inputs_hash`, `decision_trace` fingerprint) and emits evaluated findings as separate files. - - Enforces AOC guardrails: no derived modifications to raw evidence fields. -- **Trivy (`trivy:db`, `trivy:java-db`).** - - Maps StellaOps advisory schema to Trivy DB format, handling namespace collisions and ecosystem-specific ranges. - - Validates compatibility against supported Trivy schema versions; run fails fast if mismatch. - - Emits optional manifest summarising package counts and severity distribution. -- **Mirror (`mirror:full`, `mirror:delta`).** - - Builds self-contained filesystem layout (`/manifests`, `/data/raw`, `/data/policy`, `/indexes`). - - Delta variant compares against base manifest (`base_export_id`) to write only changed artefacts; records `removed` entries for cleanup. - - Supports optional encryption of `/data` subtree (age/AES-GCM) with key wrapping stored in `provenance.json`. - -Adapters expose structured telemetry events (`adapter.start`, `adapter.chunk`, `adapter.complete`) with record counts and byte totals per chunk. Failures emit `adapter.error` with reason codes. - -## Signing and provenance -- **Manifest schema.** `export.json` contains run metadata, profile descriptor, selector summary, counts, SHA-256 digests, compression hints, and distribution list. Deterministic field ordering and normalized timestamps. -- **Provenance schema.** `provenance.json` captures in-toto subject listing (bundle digest, manifest digest), referenced inputs (findings ledger queries, policy snapshot ids, SBOM identifiers), tool version (`exporter_version`, adapter versions), and KMS key identifiers. -- **Attestation.** Cosign SLSA Level 2 template by default; optional SLSA Level 3 when supply chain attestations are enabled. Detached signatures stored alongside manifests; CLI/Console encourage `cosign verify --key ` workflow. -- **Audit trail.** Each run stores success/failure status, signature identifiers, and verification hints for downstream automation (CI pipelines, offline verification scripts). - -## Distribution flows -- **HTTP download.** Console and CLI stream bundles via chunked transfer; supports range requests and resumable downloads. Response includes `X-Export-Digest`, `X-Export-Length`, and optional encryption metadata. -- **OCI push.** Worker uses ORAS to publish bundles as OCI artefacts with annotations describing profile, tenant, manifest digest, and provenance reference. Supports multi-tenant registries with `repository-per-tenant` naming. -- **Object storage.** Writes to tenant-prefixed paths (`s3://stella-exports/{tenant}/{run-id}/...`) with immutable retention policies. Retention scheduler purges expired runs based on profile configuration. -- **Offline Kit seeding.** Mirror bundles optionally staged into Offline Kit assembly pipelines, inheriting the same manifests and signatures. - -## Observability -- **Metrics.** Emits `exporter_run_duration_seconds`, `exporter_run_bytes_total{profile}`, `exporter_run_failures_total{error_code}`, `exporter_active_runs{tenant}`, `exporter_distribution_push_seconds{type}`. -- **Logs.** Structured logs with fields `run_id`, `tenant`, `profile_kind`, `adapter`, `phase`, `correlation_id`, `error_code`. Phases include `plan`, `resolve`, `adapter`, `manifest`, `sign`, `distribute`. -- **Traces.** Optional OpenTelemetry spans (`export.plan`, `export.fetch`, `export.write`, `export.sign`, `export.distribute`) for cross-service correlation. -- **Dashboards & alerts.** DevOps pipeline seeds Grafana dashboards summarising throughput, size, failure ratios, and distribution latency. Alert thresholds: failure rate >5% per profile, median run duration >p95 baseline, signature verification failures >0. - -## Security posture -- Tenant claim enforced at every query and distribution path; cross-tenant selectors rejected unless explicit cross-tenant mirror feature toggled with signed approval. -- RBAC scopes: `export:profile:manage`, `export:run`, `export:read`, `export:download`. Console hides actions without scope; CLI returns `401/403`. -- Encryption options configurable per profile; keys derived from Authority-managed KMS. Mirror encryption uses tenant-specific recipients; JSON/Trivy rely on transport security plus optional encryption at rest. -- Restart-only plugin loading ensures adapters and distribution drivers are vetted at deployment time, reducing runtime injection risks. -- Deterministic output ensures tamper detection via content hashes; provenance links to source runs and policy snapshots to maintain auditability. - -## Deployment considerations -- Packaged as separate API and worker containers. Helm chart and compose overlays define horizontal scaling, worker concurrency, queue leases, and object storage credentials. -- Requires Authority client credentials for KMS and optional registry credentials stored via sealed secrets. -- Offline-first deployments disable OCI distribution by default and provide local object storage endpoints; HTTP downloads served via internal gateway. -- Health endpoints: `/health/ready` validates Mongo connectivity, object storage access, adapter registry integrity, and KMS signer readiness. - -## Compliance checklist -- [ ] Profiles and runs enforce tenant scoping; cross-tenant exports disabled unless approved. -- [ ] Manifests and provenance files are generated with deterministic hashes and signed via configured KMS. -- [ ] Adapters run with restart-time registration only; no runtime plugin loading. -- [ ] Distribution drivers respect allowlist; OCI push disabled when offline mode is active. -- [ ] Metrics, logs, and traces follow observability guidelines; dashboards and alerts configured. -- [ ] Retention policies and pruning jobs configured for staged bundles. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center Architecture + +> Derived from Epic 10 – Export Center and the subsequent export adapter deep dives. + +The Export Center is the dedicated service layer that packages StellaOps evidence and policy overlays into reproducible bundles. It runs as a multi-surface API backed by asynchronous workers and format adapters, enforcing Aggregation-Only Contract (AOC) guardrails while providing deterministic manifests, signing, and distribution paths. + +## Runtime topology +- **Export Center API (`StellaOps.ExportCenter.WebService`).** Receives profile CRUD, export run requests, status queries, and download streams through the unified Web API gateway. Enforces tenant scopes, RBAC, quotas, and concurrency guards. +- **Export Center Worker (`StellaOps.ExportCenter.Worker`).** Dequeues export jobs from the Orchestrator, resolves selectors, invokes adapters, and writes manifests and bundle artefacts. Stateless; scales horizontally. +- **Backing stores.** + - MongoDB collections: `export_profiles`, `export_runs`, `export_inputs`, `export_distributions`, `export_events`. + - Object storage bucket or filesystem for staging bundle payloads. + - Optional registry/object storage credentials injected via Authority-scoped secrets. +- **Integration peers.** + - **Findings Ledger** for advisory, VEX, SBOM payload streaming. + - **Policy Engine** for deterministic policy snapshots and evaluated findings. + - **Orchestrator** for job scheduling, quotas, and telemetry fan-out. + - **Authority** for tenant-aware access tokens and KMS key references. + - **Console & CLI** as presentation surfaces consuming the API. + +## Job lifecycle +1. **Profile selection.** Operator or automation picks a profile (`json:raw`, `json:policy`, `trivy:db`, `trivy:java-db`, `mirror:full`, `mirror:delta`) and submits scope selectors (tenant, time window, products, SBOM subjects, ecosystems). See `docs/modules/export-center/profiles.md` for profile definitions and configuration fields. +2. **Planner resolution.** API validates selectors, expands include/exclude lists, and writes a pending `export_run` with immutable parameters and deterministic ordering hints. +3. **Orchestrator dispatch.** `export_run` triggers a job lease via Orchestrator with quotas per tenant/profile and concurrency caps (default 4 active per tenant). +4. **Worker execution.** Worker streams data from Findings Ledger and Policy Engine using pagination cursors. Adapters write canonical payloads to staging storage, compute checksums, and emit streaming progress events (SSE). +5. **Manifest and provenance emission.** Worker writes `export.json` and `provenance.json`, signs them with configured KMS keys (cosign-compatible), and uploads signatures alongside content. +6. **Distribution registration.** Worker records available distribution methods (download URL, OCI reference, object storage path), raises completion/failure events, and exposes metrics/logs. +7. **Download & verification.** Clients download bundles or pull OCI artefacts, verify signatures, and consume provenance to trace source artefacts. + +Cancellation requests mark runs as `aborted` and cause workers to stop iterating sources; partially written files are destroyed and the run is marked with an audit entry. + +## Core components +### API surface +- Detailed request and response payloads are catalogued in `docs/modules/export-center/api.md`. +- **Profiles API.** + - `GET /api/export/profiles`: list tenant-scoped profiles. + - `POST /api/export/profiles`: create custom profiles (variants of JSON, Trivy, mirror) with validated configuration schema. + - `PATCH /api/export/profiles/{id}`: update metadata; config changes clone new revision to preserve determinism. +- **Runs API.** + - `POST /api/export/runs`: submit export run for a profile with selectors and options (policy snapshot id, mirror base manifest). + - `GET /api/export/runs/{id}`: status, progress counters, provenance summary. + - `GET /api/export/runs/{id}/events`: server-sent events with state transitions, adapter milestones, signing status. + - `POST /api/export/runs/{id}/cancel`: cooperative cancellation with audit logging. +- **Downloads API.** + - `GET /api/export/runs/{id}/download`: streaming download with range support and checksum trailers. + - `GET /api/export/runs/{id}/manifest`: signed `export.json`. + - `GET /api/export/runs/{id}/provenance`: signed `provenance.json`. + +All endpoints require Authority-issued JWT + DPoP tokens with scopes `export:run`, `export:read`, and tenant claim alignment. Rate-limiting and quotas surface via `X-Stella-Quota-*` headers. + +### Worker pipeline +- **Input resolvers.** Query Findings Ledger and Policy Engine using stable pagination (Mongo `_id` ascending, or resume tokens for change streams). Selector expressions compile into Mongo filter fragments and/or API query parameters. +- **Adapter host.** Adapter plugin loader (restart-time only) resolves profile variant to adapter implementation. Adapters present a deterministic `RunAsync(context)` contract with streaming writers and telemetry instrumentation. +- **Content writers.** + - JSON adapters emit `.jsonl.zst` files with canonical ordering (tenant, subject, document id). + - Trivy adapters materialise SQLite databases or tar archives matching Trivy DB expectations; schema version gates prevent unsupported outputs. + - Mirror adapters assemble deterministic filesystem trees (manifests, indexes, payload subtrees) and, when configured, OCI artefact layers. +- **Manifest generator.** Aggregates counts, bytes, hash digests (SHA-256), profile metadata, and input references. Writes `export.json` and `provenance.json` using canonical JSON (sorted keys, RFC3339 UTC timestamps). +- **Signing service.** Integrates with platform KMS via Authority (default cosign signer). Produces in-toto SLSA attestations when configured. Supports detached signatures and optional in-bundle signatures. +- **Distribution drivers.** `dist-http` exposes staged files via download endpoint; `dist-oci` pushes artefacts to registries using ORAS with digest pinning; `dist-objstore` uploads to tenant-specific prefixes with immutability flags. + +## Data model snapshots + +| Collection | Purpose | Key fields | Notes | +|------------|---------|------------|-------| +| `export_profiles` | Profile definitions (kind, variant, config). | `_id`, `tenant`, `name`, `kind`, `variant`, `config_json`, `created_by`, `created_at`. | Config includes adapter parameters (included record types, compression, encryption). | +| `export_runs` | Run state machine and audit info. | `_id`, `profile_id`, `tenant`, `status`, `requested_by`, `selectors`, `policy_snapshot_id`, `started_at`, `completed_at`, `duration_ms`, `error_code`. | Immutable selectors; status transitions recorded in `export_events`. | +| `export_inputs` | Resolved input ranges. | `run_id`, `source`, `cursor`, `count`, `hash`. | Enables resumable retries and audit. | +| `export_distributions` | Distribution artefacts. | `run_id`, `type` (`http`, `oci`, `object`), `location`, `sha256`, `size_bytes`, `expires_at`. | `expires_at` used for retention policies and automatic pruning. | +| `export_events` | Timeline of state transitions and metrics. | `run_id`, `event_type`, `message`, `at`, `metrics`. | Feeds SSE stream and audit trails. | + +## Adapter responsibilities +- **JSON (`json:raw`, `json:policy`).** + - Ensures canonical casing, timezone normalization, and linkset preservation. + - Policy variant embeds policy snapshot metadata (`policy_version`, `inputs_hash`, `decision_trace` fingerprint) and emits evaluated findings as separate files. + - Enforces AOC guardrails: no derived modifications to raw evidence fields. +- **Trivy (`trivy:db`, `trivy:java-db`).** + - Maps StellaOps advisory schema to Trivy DB format, handling namespace collisions and ecosystem-specific ranges. + - Validates compatibility against supported Trivy schema versions; run fails fast if mismatch. + - Emits optional manifest summarising package counts and severity distribution. +- **Mirror (`mirror:full`, `mirror:delta`).** + - Builds self-contained filesystem layout (`/manifests`, `/data/raw`, `/data/policy`, `/indexes`). + - Delta variant compares against base manifest (`base_export_id`) to write only changed artefacts; records `removed` entries for cleanup. + - Supports optional encryption of `/data` subtree (age/AES-GCM) with key wrapping stored in `provenance.json`. + +Adapters expose structured telemetry events (`adapter.start`, `adapter.chunk`, `adapter.complete`) with record counts and byte totals per chunk. Failures emit `adapter.error` with reason codes. + +## Signing and provenance +- **Manifest schema.** `export.json` contains run metadata, profile descriptor, selector summary, counts, SHA-256 digests, compression hints, and distribution list. Deterministic field ordering and normalized timestamps. +- **Provenance schema.** `provenance.json` captures in-toto subject listing (bundle digest, manifest digest), referenced inputs (findings ledger queries, policy snapshot ids, SBOM identifiers), tool version (`exporter_version`, adapter versions), and KMS key identifiers. +- **Attestation.** Cosign SLSA Level 2 template by default; optional SLSA Level 3 when supply chain attestations are enabled. Detached signatures stored alongside manifests; CLI/Console encourage `cosign verify --key ` workflow. +- **Audit trail.** Each run stores success/failure status, signature identifiers, and verification hints for downstream automation (CI pipelines, offline verification scripts). + +## Distribution flows +- **HTTP download.** Console and CLI stream bundles via chunked transfer; supports range requests and resumable downloads. Response includes `X-Export-Digest`, `X-Export-Length`, and optional encryption metadata. +- **OCI push.** Worker uses ORAS to publish bundles as OCI artefacts with annotations describing profile, tenant, manifest digest, and provenance reference. Supports multi-tenant registries with `repository-per-tenant` naming. +- **Object storage.** Writes to tenant-prefixed paths (`s3://stella-exports/{tenant}/{run-id}/...`) with immutable retention policies. Retention scheduler purges expired runs based on profile configuration. +- **Offline Kit seeding.** Mirror bundles optionally staged into Offline Kit assembly pipelines, inheriting the same manifests and signatures. + +## Observability +- **Metrics.** Emits `exporter_run_duration_seconds`, `exporter_run_bytes_total{profile}`, `exporter_run_failures_total{error_code}`, `exporter_active_runs{tenant}`, `exporter_distribution_push_seconds{type}`. +- **Logs.** Structured logs with fields `run_id`, `tenant`, `profile_kind`, `adapter`, `phase`, `correlation_id`, `error_code`. Phases include `plan`, `resolve`, `adapter`, `manifest`, `sign`, `distribute`. +- **Traces.** Optional OpenTelemetry spans (`export.plan`, `export.fetch`, `export.write`, `export.sign`, `export.distribute`) for cross-service correlation. +- **Dashboards & alerts.** DevOps pipeline seeds Grafana dashboards summarising throughput, size, failure ratios, and distribution latency. Alert thresholds: failure rate >5% per profile, median run duration >p95 baseline, signature verification failures >0. + +## Security posture +- Tenant claim enforced at every query and distribution path; cross-tenant selectors rejected unless explicit cross-tenant mirror feature toggled with signed approval. +- RBAC scopes: `export:profile:manage`, `export:run`, `export:read`, `export:download`. Console hides actions without scope; CLI returns `401/403`. +- Encryption options configurable per profile; keys derived from Authority-managed KMS. Mirror encryption uses tenant-specific recipients; JSON/Trivy rely on transport security plus optional encryption at rest. +- Restart-only plugin loading ensures adapters and distribution drivers are vetted at deployment time, reducing runtime injection risks. +- Deterministic output ensures tamper detection via content hashes; provenance links to source runs and policy snapshots to maintain auditability. + +## Deployment considerations +- Packaged as separate API and worker containers. Helm chart and compose overlays define horizontal scaling, worker concurrency, queue leases, and object storage credentials. +- Requires Authority client credentials for KMS and optional registry credentials stored via sealed secrets. +- Offline-first deployments disable OCI distribution by default and provide local object storage endpoints; HTTP downloads served via internal gateway. +- Health endpoints: `/health/ready` validates Mongo connectivity, object storage access, adapter registry integrity, and KMS signer readiness. + +## Compliance checklist +- [ ] Profiles and runs enforce tenant scoping; cross-tenant exports disabled unless approved. +- [ ] Manifests and provenance files are generated with deterministic hashes and signed via configured KMS. +- [ ] Adapters run with restart-time registration only; no runtime plugin loading. +- [ ] Distribution drivers respect allowlist; OCI push disabled when offline mode is active. +- [ ] Metrics, logs, and traces follow observability guidelines; dashboards and alerts configured. +- [ ] Retention policies and pruning jobs configured for staged bundles. + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/export-center/cli.md b/docs/modules/export-center/cli.md similarity index 96% rename from docs/export-center/cli.md rename to docs/modules/export-center/cli.md index 2cbf08bf..47920632 100644 --- a/docs/export-center/cli.md +++ b/docs/modules/export-center/cli.md @@ -1,231 +1,231 @@ -# Stella CLI - Export Center Commands - -> **Audience:** Operators, release engineers, and CI maintainers using the `stella` CLI to manage Export Center profiles and runs. -> **Supported from:** `stella` CLI >= 0.22.0 (Export Center Phase 1). -> **Prerequisites:** Authority token with the scopes noted per command (`export:profile:manage`, `export:run`, `export:read`, `export:download`). - -Use this guide with the [Export Center API reference](api.md) and [Profiles](profiles.md) catalogue. The CLI wraps the same REST endpoints, preserving deterministic behaviour and guardrails. - -> Status: CLI support is tracked under `CLI-EXPORT-35-001` and `CLI-EXPORT-36-001`. The current CLI build does not yet surface these commands; treat this guide as the target contract and adjust once implementations merge. - -## 1. Global options and configuration - -| Flag | Default | Description | -|------|---------|-------------| -| `--server ` | `https://stella.local` | Gateway root. Matches `STELLA_SERVER`. | -| `--tenant ` | Token tenant | Override tenant for multi-tenant tokens. | -| `--profile ` | none | Loads saved defaults from `~/.stella/profiles/.toml`. | -| `--output ` | stdout | Redirect full JSON response. | -| `--format ` | `table` on TTY | Controls table formatting for list commands. | -| `--trace` | false | Emit request timing and correlation ids. | - -Environment variables: `STELLA_TOKEN`, `STELLA_SERVER`, `STELLA_TENANT`, `STELLA_PROFILE`. - -Exit codes align with API error codes (see section 6). - -## 2. Profile management commands - -### 2.1 `stella export profile list` - -List profiles for the current tenant. - -``` -stella export profile list --kind json --variant raw --format table -``` - -Outputs columns `PROFILE`, `KIND`, `VARIANT`, `DISTRIBUTION`, `RETENTION`. Use `--format json` for automation. - -### 2.2 `stella export profile show` - -``` -stella export profile show prof-json-raw --output profile.json -``` - -Fetches full configuration and writes it to file. - -### 2.3 `stella export profile create` - -``` -stella export profile create --file profiles/prof-json-raw.json -``` - -JSON schema matches `POST /api/export/profiles`. CLI validates against built-in schema before submission. Requires `export:profile:manage`. - -### 2.4 `stella export profile update` - -``` -stella export profile update prof-json-raw \ - --retention "days:21" \ - --distribution http,object -``` - -Supports toggling retention, adding/removing distribution targets, and renaming. Structural changes (kind, variant, include set) require editing the JSON and using `--replace-file` to create a new revision. - -### 2.5 `stella export profile archive` - -``` -stella export profile archive prof-json-raw --reason "Superseded by Phase 2 profile" -``` - -Marks the profile inactive. Use `stella export profile restore` to re-activate. - -## 3. Run lifecycle commands - -### 3.1 `stella export run submit` - -``` -stella export run submit prof-json-raw \ - --selector tenant=acme \ - --selector product=registry.example.com/app:* \ - --selector time=2025-10-01T00:00:00Z,2025-10-29T00:00:00Z \ - --policy-snapshot policy-snap-42 \ - --allow-empty=false -``` - -Selectors accept `key=value` pairs; use `time=,` for windows. The command prints the `runId` and initial status. - -### 3.2 `stella export run ls` - -``` -stella export run ls --profile prof-json-raw --status active --tail 5 -``` - -Shows recent runs with columns `RUN`, `PROFILE`, `STATUS`, `PROGRESS`, `UPDATED`. - -### 3.3 `stella export run show` - -``` -stella export run show run-20251029-01 --format json -``` - -Outputs full metadata, progress counters, distribution descriptors, and links. - -### 3.4 `stella export run watch` - -``` -stella export run watch run-20251029-01 --follow -``` - -Streams server-sent events and renders a live progress bar. `--json` prints raw events for scripting. - -### 3.5 `stella export run cancel` - -``` -stella export run cancel run-20251029-01 --reason "Replacing with refined selectors" -``` - -Gracefully cancels the run; exit code `0` indicates cancellation request accepted. - -## 4. Download and verification commands - -### 4.1 `stella export download` - -``` -stella export download run-20251029-01 \ - --output out/exports/run-20251029-01.tar.zst \ - --resume -``` - -Downloads the primary bundle. `--resume` enables HTTP range requests; the CLI checkpoints progress to `.part` files. - -### 4.2 `stella export manifest` - -``` -stella export manifest run-20251029-01 --output manifests/export.json -``` - -Fetches the signed manifest. Use `--signature manifests/export.json.sig` to save the detached signature. - -### 4.3 `stella export provenance` - -``` -stella export provenance run-20251029-01 --output manifests/provenance.json -``` - -Retrieves the signed provenance file. `--signature` behaves like the manifest command. - -### 4.4 `stella export verify` - -``` -stella export verify run-20251029-01 \ - --manifest manifests/export.json \ - --provenance manifests/provenance.json \ - --key keys/acme-export.pub -``` - -Wrapper around `cosign verify`. Returns exit `0` when signatures and digests validate. Exit `20` when verification fails. - -## 5. CI recipe (GitHub Actions example) - -```yaml -name: Export Center Bundle -on: - workflow_dispatch: -jobs: - export: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install Stella CLI - run: curl -sSfL https://downloads.stellaops.org/cli/install.sh | sh - - name: Submit export run - env: - STELLA_TOKEN: ${{ secrets.STELLA_TOKEN }} - run: | - run_id=$(stella export run submit prof-json-raw \ - --selector tenant=acme \ - --selector product=registry.example.com/app:* \ - --allow-empty=false \ - --format json | jq -r '.runId') - echo "RUN_ID=$run_id" >> $GITHUB_ENV - - name: Wait for completion - env: - STELLA_TOKEN: ${{ secrets.STELLA_TOKEN }} - run: | - stella export run watch "$RUN_ID" --json \ - | tee artifacts/run.log \ - | jq -e 'select(.event == "run.succeeded")' > /dev/null - - name: Download bundle - env: - STELLA_TOKEN: ${{ secrets.STELLA_TOKEN }} - run: | - stella export download "$RUN_ID" --output artifacts/export.tar.zst --resume - stella export manifest "$RUN_ID" --output artifacts/export.json --signature artifacts/export.json.sig - stella export provenance "$RUN_ID" --output artifacts/provenance.json --signature artifacts/provenance.json.sig - - name: Verify signatures - run: | - stella export verify "$RUN_ID" \ - --manifest artifacts/export.json \ - --provenance artifacts/provenance.json \ - --key keys/acme-export.pub -``` - -## 6. Exit codes - -| Code | Meaning | -|------|---------| -| `0` | Command succeeded. | -| `10` | Validation error (`ERR_EXPORT_001`). | -| `11` | Profile missing or inaccessible (`ERR_EXPORT_002`). | -| `12` | Quota or concurrency exceeded (`ERR_EXPORT_003` or `ERR_EXPORT_QUOTA`). | -| `13` | Run failed due to adapter/signing/distribution error. | -| `20` | Verification failure (`stella export verify`). | -| `21` | Download incomplete after retries (network errors). | -| `30` | CLI configuration error (missing token, invalid profile file). | - -Exit codes above 100 are reserved for future profile-specific tooling. - -## 7. Offline usage notes - -- Use profiles that enable `object` distribution with local object storage endpoints. CLI reads `STELLA_EXPORT_OBJECT_ENDPOINT` when provided (falls back to gateway). -- Mirror bundles work offline by skipping OCI distribution. CLI adds `--offline` to bypass OCI checks. -- `stella export verify` works fully offline when provided with tenant public keys (packaged in Offline Kit). - -## 8. Related documentation - -- [Export Center Profiles](profiles.md) -- [Export Center API reference](api.md) -- [Export Center Architecture](architecture.md) -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Stella CLI - Export Center Commands + +> **Audience:** Operators, release engineers, and CI maintainers using the `stella` CLI to manage Export Center profiles and runs. +> **Supported from:** `stella` CLI >= 0.22.0 (Export Center Phase 1). +> **Prerequisites:** Authority token with the scopes noted per command (`export:profile:manage`, `export:run`, `export:read`, `export:download`). + +Use this guide with the [Export Center API reference](api.md) and [Profiles](profiles.md) catalogue. The CLI wraps the same REST endpoints, preserving deterministic behaviour and guardrails. + +> Status: CLI support is tracked under `CLI-EXPORT-35-001` and `CLI-EXPORT-36-001`. The current CLI build does not yet surface these commands; treat this guide as the target contract and adjust once implementations merge. + +## 1. Global options and configuration + +| Flag | Default | Description | +|------|---------|-------------| +| `--server ` | `https://stella.local` | Gateway root. Matches `STELLA_SERVER`. | +| `--tenant ` | Token tenant | Override tenant for multi-tenant tokens. | +| `--profile ` | none | Loads saved defaults from `~/.stella/profiles/.toml`. | +| `--output ` | stdout | Redirect full JSON response. | +| `--format ` | `table` on TTY | Controls table formatting for list commands. | +| `--trace` | false | Emit request timing and correlation ids. | + +Environment variables: `STELLA_TOKEN`, `STELLA_SERVER`, `STELLA_TENANT`, `STELLA_PROFILE`. + +Exit codes align with API error codes (see section 6). + +## 2. Profile management commands + +### 2.1 `stella export profile list` + +List profiles for the current tenant. + +``` +stella export profile list --kind json --variant raw --format table +``` + +Outputs columns `PROFILE`, `KIND`, `VARIANT`, `DISTRIBUTION`, `RETENTION`. Use `--format json` for automation. + +### 2.2 `stella export profile show` + +``` +stella export profile show prof-json-raw --output profile.json +``` + +Fetches full configuration and writes it to file. + +### 2.3 `stella export profile create` + +``` +stella export profile create --file profiles/prof-json-raw.json +``` + +JSON schema matches `POST /api/export/profiles`. CLI validates against built-in schema before submission. Requires `export:profile:manage`. + +### 2.4 `stella export profile update` + +``` +stella export profile update prof-json-raw \ + --retention "days:21" \ + --distribution http,object +``` + +Supports toggling retention, adding/removing distribution targets, and renaming. Structural changes (kind, variant, include set) require editing the JSON and using `--replace-file` to create a new revision. + +### 2.5 `stella export profile archive` + +``` +stella export profile archive prof-json-raw --reason "Superseded by Phase 2 profile" +``` + +Marks the profile inactive. Use `stella export profile restore` to re-activate. + +## 3. Run lifecycle commands + +### 3.1 `stella export run submit` + +``` +stella export run submit prof-json-raw \ + --selector tenant=acme \ + --selector product=registry.example.com/app:* \ + --selector time=2025-10-01T00:00:00Z,2025-10-29T00:00:00Z \ + --policy-snapshot policy-snap-42 \ + --allow-empty=false +``` + +Selectors accept `key=value` pairs; use `time=,` for windows. The command prints the `runId` and initial status. + +### 3.2 `stella export run ls` + +``` +stella export run ls --profile prof-json-raw --status active --tail 5 +``` + +Shows recent runs with columns `RUN`, `PROFILE`, `STATUS`, `PROGRESS`, `UPDATED`. + +### 3.3 `stella export run show` + +``` +stella export run show run-20251029-01 --format json +``` + +Outputs full metadata, progress counters, distribution descriptors, and links. + +### 3.4 `stella export run watch` + +``` +stella export run watch run-20251029-01 --follow +``` + +Streams server-sent events and renders a live progress bar. `--json` prints raw events for scripting. + +### 3.5 `stella export run cancel` + +``` +stella export run cancel run-20251029-01 --reason "Replacing with refined selectors" +``` + +Gracefully cancels the run; exit code `0` indicates cancellation request accepted. + +## 4. Download and verification commands + +### 4.1 `stella export download` + +``` +stella export download run-20251029-01 \ + --output out/exports/run-20251029-01.tar.zst \ + --resume +``` + +Downloads the primary bundle. `--resume` enables HTTP range requests; the CLI checkpoints progress to `.part` files. + +### 4.2 `stella export manifest` + +``` +stella export manifest run-20251029-01 --output manifests/export.json +``` + +Fetches the signed manifest. Use `--signature manifests/export.json.sig` to save the detached signature. + +### 4.3 `stella export provenance` + +``` +stella export provenance run-20251029-01 --output manifests/provenance.json +``` + +Retrieves the signed provenance file. `--signature` behaves like the manifest command. + +### 4.4 `stella export verify` + +``` +stella export verify run-20251029-01 \ + --manifest manifests/export.json \ + --provenance manifests/provenance.json \ + --key keys/acme-export.pub +``` + +Wrapper around `cosign verify`. Returns exit `0` when signatures and digests validate. Exit `20` when verification fails. + +## 5. CI recipe (GitHub Actions example) + +```yaml +name: Export Center Bundle +on: + workflow_dispatch: +jobs: + export: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Stella CLI + run: curl -sSfL https://downloads.stellaops.org/cli/install.sh | sh + - name: Submit export run + env: + STELLA_TOKEN: ${{ secrets.STELLA_TOKEN }} + run: | + run_id=$(stella export run submit prof-json-raw \ + --selector tenant=acme \ + --selector product=registry.example.com/app:* \ + --allow-empty=false \ + --format json | jq -r '.runId') + echo "RUN_ID=$run_id" >> $GITHUB_ENV + - name: Wait for completion + env: + STELLA_TOKEN: ${{ secrets.STELLA_TOKEN }} + run: | + stella export run watch "$RUN_ID" --json \ + | tee artifacts/run.log \ + | jq -e 'select(.event == "run.succeeded")' > /dev/null + - name: Download bundle + env: + STELLA_TOKEN: ${{ secrets.STELLA_TOKEN }} + run: | + stella export download "$RUN_ID" --output artifacts/export.tar.zst --resume + stella export manifest "$RUN_ID" --output artifacts/export.json --signature artifacts/export.json.sig + stella export provenance "$RUN_ID" --output artifacts/provenance.json --signature artifacts/provenance.json.sig + - name: Verify signatures + run: | + stella export verify "$RUN_ID" \ + --manifest artifacts/export.json \ + --provenance artifacts/provenance.json \ + --key keys/acme-export.pub +``` + +## 6. Exit codes + +| Code | Meaning | +|------|---------| +| `0` | Command succeeded. | +| `10` | Validation error (`ERR_EXPORT_001`). | +| `11` | Profile missing or inaccessible (`ERR_EXPORT_002`). | +| `12` | Quota or concurrency exceeded (`ERR_EXPORT_003` or `ERR_EXPORT_QUOTA`). | +| `13` | Run failed due to adapter/signing/distribution error. | +| `20` | Verification failure (`stella export verify`). | +| `21` | Download incomplete after retries (network errors). | +| `30` | CLI configuration error (missing token, invalid profile file). | + +Exit codes above 100 are reserved for future profile-specific tooling. + +## 7. Offline usage notes + +- Use profiles that enable `object` distribution with local object storage endpoints. CLI reads `STELLA_EXPORT_OBJECT_ENDPOINT` when provided (falls back to gateway). +- Mirror bundles work offline by skipping OCI distribution. CLI adds `--offline` to bypass OCI checks. +- `stella export verify` works fully offline when provided with tenant public keys (packaged in Offline Kit). + +## 8. Related documentation + +- [Export Center Profiles](profiles.md) +- [Export Center API reference](api.md) +- [Export Center Architecture](architecture.md) +- [Aggregation-Only Contract reference](../../ingestion/aggregation-only-contract.md) + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/modules/export-center/implementation_plan.md b/docs/modules/export-center/implementation_plan.md new file mode 100644 index 00000000..490616b4 --- /dev/null +++ b/docs/modules/export-center/implementation_plan.md @@ -0,0 +1,66 @@ +# Implementation plan — Export Center + +## Delivery phases +- **Phase 1 – JSON & mirror foundations** + Stand up the Export Center service + worker, deliver canonical JSON (`json:raw`, `json:policy`) and `mirror:full` profiles as download-only bundles, seed schema migrations, and publish manifest/provenance formats. +- **Phase 2 – Trivy adapters & distribution** + Implement Trivy DB / Java DB adapters, wire OCI/object storage distribution paths, and expose policy snapshot embedding + verification tooling. +- **Phase 3 – Delta, encryption, scheduling** + Release mirror deltas, bundle encryption, advanced scheduling/automation, resumable downloads, and CLI/Console verification workflows. + +## Component work breakdown +- **Service & worker** + - Define migrations for `export_profiles`, `export_runs`, `export_inputs`, `export_distributions`. + - Implement planner, adapter host, signing/attestation layer, distribution engines, and deterministic manifests. + - Enforce tenant quotas, concurrency controls, and audit logging for create/cancel/distribute events. +- **Adapters** + - JSON adapters: canonical JSONL writers, redaction guardrails, compression (zstd). + - Trivy adapters: field mapping, schema compatibility gating, validation suite. + - Mirror adapters: filesystem/OCI layout, delta computation, optional encryption with manifest updates. +- **Integrations** + - Findings Ledger streaming APIs for advisories, VEX, SBOMs, findings. + - Policy Engine deterministic snapshot endpoint; VEX Lens consensus snapshot. + - Export Center telemetry surfaced through Observability stack. +- **Surfaces** + - Console: profiles CRUD, run wizard, run detail + verification panel, distribution dashboards. + - CLI: `stella export profile|run|download|verify` with resumable downloads and signature verification. +- **Security / RBAC** + - Scope enforcement per tenant, role matrix coverage, encryption key rotation tests, redaction filters. +- **Docs & ops** + - Author module dossier (overview, architecture, profiles, API, CLI, mirror bundles, Trivy adapter, provenance & signing). + - Produce runbooks (`docs/operations/export-runbook.md`) and hardening guidance (`docs/security/export-hardening.md`). + +## Documentation deliverables +- `docs/modules/export-center/overview.md` — responsibilities, profiles, surfaces. +- `docs/modules/export-center/architecture.md` — service topology, adapters, manifests, distribution flow. +- `docs/modules/export-center/profiles.md`, `trivy-adapter.md`, `mirror-bundles.md`, `provenance-and-signing.md`, `api.md`, `cli.md` — keep aligned with shipped features. +- Cross-link Orchestrator, Policy, VEX Lens, CLI, and Offline Kit docs whenever exports become dependencies. + +## Acceptance criteria +- Operators can create, monitor, and download an export; `cosign verify` (and CLI verify) succeeds against manifest + provenance, mapping back to source artifacts. +- Trivy bundles import cleanly into Trivy across supported versions; mirror bundles run in Offline Kit reference environment (full + delta). +- Policy snapshot runs reproduce deterministic decisions and include embedded `policyVersion` + `inputsHash`. +- Tenant scoping and RBAC block unauthorized actions; encryption-enabled bundles lock data to recipient keys. +- Metrics (`exporter_run_duration_seconds`, `exporter_bundle_bytes_total`, `exporter_run_failures_total`) and dashboards reflect live runs; alerts trigger on sustained failure rates. +- Retried runs remain idempotent: manifests, hashes, and distribution artefacts match across identical inputs. + +## Risks & mitigations +- **Schema drift (Trivy / policy):** versioned adapters with compatibility gates, CI integration tests, fail-fast with actionable errors. +- **Bundle bloat:** zstd compression, sharding, delta exports, OCI dedupe. +- **Data leakage:** strict schema allowlists, tenancy filters, redaction enforcement, encryption options. +- **Non-determinism:** embed policy snapshots, enforce deterministic ordering, include content hashes in manifest. +- **Operational slowness:** streaming downloads with range support, resumable CLI, concurrency limits, retry policies for workers. + +## Test strategy +- **Unit:** adapter mapping, manifest hashing, signing/attestation, delta computation, encryption round-trips. +- **Integration:** end-to-end runs for every profile, verification workflows, OCI push/pull, resume/abort scenarios. +- **Compatibility:** matrix tests for Trivy versions, mirror bundle import in Offline Kit sample environment. +- **Security:** tenant fuzzing, RBAC coverage, redaction/PII filters, key rotation. +- **Performance & chaos:** stress exports with large datasets, simulate worker/API failures mid-run, confirm deterministic recovery. + +## Definition of done +- Service, worker, and adapters deployed with telemetry & alerting. +- CLI & Console workflows published, Offline Kit instructions updated. +- Documentation set listed above refreshed; imposed rule statements appended where required. +- CI pipelines include schema validation, profile verification, and determinism checks. +- ./TASKS.md + ../../TASKS.md reflect current status for in-flight stories. diff --git a/docs/export-center/mirror-bundles.md b/docs/modules/export-center/mirror-bundles.md similarity index 95% rename from docs/export-center/mirror-bundles.md rename to docs/modules/export-center/mirror-bundles.md index b01c8ffa..94ae8040 100644 --- a/docs/export-center/mirror-bundles.md +++ b/docs/modules/export-center/mirror-bundles.md @@ -1,202 +1,202 @@ -# Export Center Mirror Bundles - -Mirror bundles package StellaOps evidence, policy overlays, and indexes for air-gapped or bandwidth-constrained environments. They are produced by the `mirror:full` and `mirror:delta` profiles described in Epic 10 (Export Center) and implemented across Sprints 35-37 (`EXPORT-SVC-35-004`, `EXPORT-SVC-37-001`, `EXPORT-SVC-37-002`). This guide details bundle layouts, delta mechanics, encryption workflow, import procedures, and operational best practices. - -> Export Center workers are being wired while this document is written. Treat the content as the target contract for adapter development and update specifics as the implementation lands. - -## 1. Bundle overview - -| Profile | Contents | Typical use cases | Distribution | -|---------|----------|-------------------|--------------| -| `mirror:full` | Complete snapshot of raw evidence, normalized records, indexes, policy snapshots, provenance, signatures. | Initial seeding of an air-gapped mirror, disaster recovery drills. | Download bundle, optional OCI artifact. | -| `mirror:delta` | Changes since a specified base export: added/updated/removed advisories, VEX statements, SBOMs, indexes, manifests. | Incremental updates, bandwidth reduction, nightly refreshes. | Download bundle, optional OCI artifact. | - -Both profiles respect AOC boundaries: raw ingestion data remains untouched, and policy outputs live under their own directory with explicit provenance. - -## 2. Filesystem layout - -Directory structure inside the extracted bundle: - -``` -mirror/ - manifest.yaml - export.json - provenance.json - README.md - indexes/ - advisories.index.json - vex.index.json - sbom.index.json - findings.index.json - data/ - raw/ - advisories/*.jsonl.zst - vex/*.jsonl.zst - sboms//sbom.json - normalized/ - advisories/*.jsonl.zst - vex/*.jsonl.zst - policy/ - snapshot.json - evaluations.jsonl.zst - consensus/ - vex_consensus.jsonl.zst - signatures/ - export.sig - manifest.sig -``` - -`manifest.yaml` summarises profile metadata, selectors, counts, sizes, and SHA-256 digests. `export.json` and `provenance.json` mirror the JSON profile manifests and are signed using the configured KMS key. - -Example `manifest.yaml`: - -```yaml -profile: mirror:full -runId: run-20251029-01 -tenant: acme -selectors: - products: - - registry.example.com/app:* - timeWindow: - from: 2025-10-01T00:00:00Z - to: 2025-10-29T00:00:00Z -counts: - advisories: 15234 - vex: 3045 - sboms: 872 - policyEvaluations: 19876 -artifacts: - - path: data/raw/advisories/a0.jsonl.zst - sha256: 9f4b... - bytes: 7340021 -encryption: - mode: age - strict: false - recipients: - - age1tenantkey... -``` - -## 3. Delta mechanics - -Delta bundles reference a previous full or delta run via `baseExportId` and `baseManifestDigest`. They contain: - -``` -delta/ - changed/ - data/raw/advisories/*.jsonl.zst - ... - removed/ - advisories.jsonl # list of advisory IDs removed - vex.jsonl - sboms.jsonl - manifest.diff.json # summary of counts, hashes, base export metadata -``` - -- **Base lookup:** The worker verifies that the base export is reachable (download path or OCI reference). If missing, the run fails with `ERR_EXPORT_BASE_MISSING`. -- **Change detection:** Uses deterministic hashing of normalized records to compute additions/updates. Indexes are regenerated only for affected subjects. -- **Application order:** Consumers apply deltas sequentially. A `resetBaseline=true` flag instructs them to drop cached state and apply the bundle as a full refresh. - -Example `manifest.diff.json` (delta): - -```json -{ - "baseExportId": "run-20251025-01", - "baseManifestDigest": "sha256:aa11...", - "resetBaseline": false, - "added": { - "advisories": 43, - "vex": 12, - "sboms": 5 - }, - "changed": { - "advisories": 18, - "vex": 7 - }, - "removed": { - "advisories": 2, - "vex": 0, - "sboms": 0 - } -} -``` - -## 4. Encryption workflow - -Mirror bundles support optional encryption of the `data/` subtree: - -- **Algorithm:** Age (X25519) or AES-GCM (256-bit) based on profile configuration. -- **Key wrapping:** Keys fetched from Authority-managed KMS through Export Center. Wrapped data keys stored in `provenance.json` under `encryption.recipients[]`. -- **Metadata:** `manifest.yaml` records `encryption.mode`, `recipients`, and `encryptedPaths`. -- **Strict mode:** `strict=true` encrypts everything except `manifest.yaml` and `export.json`. Default (`false`) leaves manifests unencrypted to simplify discovery. -- **Verification:** CLI (`stella export verify`) and Offline Kit scripts perform signature checks prior to decryption. - -Operators must distribute recipient keys out of band. Export Center does not transmit private keys. - -## 5. Import workflow - -### 5.1 Offline Kit - -Offline Kit bundles reference the latest full mirror export plus the last `N` deltas. Administrators run: - -``` -./offline-kit/bin/mirror import /path/to/mirror-20251029-full.tar.zst -./offline-kit/bin/mirror import /path/to/mirror-20251030-delta.tar.zst -``` - -The tool verifies signatures, applies deltas, and updates the mirror index served by the local gateway. - -### 5.2 Custom automation - -1. Download bundle (`stella export download`) and verify signatures (`stella export verify`). -2. Extract archive into a staging directory. -3. For encrypted bundles, decrypt using the provided age/AES key. -4. Sync `mirror/data` onto the target mirror store (object storage, NFS, etc.). -5. Republish indexes or reload services that depend on the mirror. - -Delta consumers must track `appliedExportIds` to ensure ordering. - -Sequence diagram of download/import: - -```mermaid -sequenceDiagram - participant CLI as stella CLI - participant Mirror as Mirror Store - participant Verify as Verification Tool - CLI->>CLI: stella export download run-20251029-01 - CLI->>Verify: stella export verify run-20251029-01 - CLI->>Mirror: mirror import mirror-20251029-full.tar.zst - CLI->>Mirror: mirror import mirror-20251030-delta.tar.zst - Mirror-->>CLI: import complete (run-20251030-02) -``` - -## 6. Operational guidance - -- **Retention:** Keep at least one full bundle plus the deltas required for disaster recovery. Configure `ExportCenter:Retention:Mirror` to prune older bundles automatically. -- **Storage footprint:** Full bundles can exceed tens of gigabytes. Plan object storage or NAS capacity accordingly and enable compression (`compression.codec=zstd`). -- **Scheduling:** For high-churn environments, run daily full exports and hourly deltas. Record cadence in `manifest.yaml` (`schedule.cron`). -- **Incident recovery:** To rebuild a mirror: - 1. Apply the most recent full bundle. - 2. Apply deltas in order of `createdAt`. - 3. Re-run integrity checks (`mirror verify `). -- **Audit logging:** Export Center logs `mirror.bundle.created`, `mirror.delta.applied`, and `mirror.encryption.enabled` events. Consume them in the central observability pipeline. - -## 7. Troubleshooting - -| Symptom | Meaning | Action | -|---------|---------|--------| -| `ERR_EXPORT_BASE_MISSING` | Base export not available | Republish base bundle or rebuild as full export. | -| Delta applies but mirror misses entries | Deltas applied out of order | Rebuild from last full bundle and reapply in sequence. | -| Decryption fails | Recipient key mismatch or corrupted bundle | Confirm key distribution and re-download bundle. | -| Verification errors | Signature mismatch | Do not import; regenerate bundle and investigate signing pipeline. | -| Manifest hash mismatch | Files changed after extraction | Re-extract bundle and re-run verification; check storage tampering. | - -## 8. References - -- [Export Center Overview](overview.md) -- [Export Center Architecture](architecture.md) -- [Export Center API reference](api.md) -- [Export Center CLI Guide](cli.md) -- [Concelier mirror runbook](../ops/concelier-mirror-operations.md) -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center Mirror Bundles + +Mirror bundles package StellaOps evidence, policy overlays, and indexes for air-gapped or bandwidth-constrained environments. They are produced by the `mirror:full` and `mirror:delta` profiles described in Epic 10 (Export Center) and implemented across Sprints 35-37 (`EXPORT-SVC-35-004`, `EXPORT-SVC-37-001`, `EXPORT-SVC-37-002`). This guide details bundle layouts, delta mechanics, encryption workflow, import procedures, and operational best practices. + +> Export Center workers are being wired while this document is written. Treat the content as the target contract for adapter development and update specifics as the implementation lands. + +## 1. Bundle overview + +| Profile | Contents | Typical use cases | Distribution | +|---------|----------|-------------------|--------------| +| `mirror:full` | Complete snapshot of raw evidence, normalized records, indexes, policy snapshots, provenance, signatures. | Initial seeding of an air-gapped mirror, disaster recovery drills. | Download bundle, optional OCI artifact. | +| `mirror:delta` | Changes since a specified base export: added/updated/removed advisories, VEX statements, SBOMs, indexes, manifests. | Incremental updates, bandwidth reduction, nightly refreshes. | Download bundle, optional OCI artifact. | + +Both profiles respect AOC boundaries: raw ingestion data remains untouched, and policy outputs live under their own directory with explicit provenance. + +## 2. Filesystem layout + +Directory structure inside the extracted bundle: + +``` +mirror/ + manifest.yaml + export.json + provenance.json + README.md + indexes/ + advisories.index.json + vex.index.json + sbom.index.json + findings.index.json + data/ + raw/ + advisories/*.jsonl.zst + vex/*.jsonl.zst + sboms//sbom.json + normalized/ + advisories/*.jsonl.zst + vex/*.jsonl.zst + policy/ + snapshot.json + evaluations.jsonl.zst + consensus/ + vex_consensus.jsonl.zst + signatures/ + export.sig + manifest.sig +``` + +`manifest.yaml` summarises profile metadata, selectors, counts, sizes, and SHA-256 digests. `export.json` and `provenance.json` mirror the JSON profile manifests and are signed using the configured KMS key. + +Example `manifest.yaml`: + +```yaml +profile: mirror:full +runId: run-20251029-01 +tenant: acme +selectors: + products: + - registry.example.com/app:* + timeWindow: + from: 2025-10-01T00:00:00Z + to: 2025-10-29T00:00:00Z +counts: + advisories: 15234 + vex: 3045 + sboms: 872 + policyEvaluations: 19876 +artifacts: + - path: data/raw/advisories/a0.jsonl.zst + sha256: 9f4b... + bytes: 7340021 +encryption: + mode: age + strict: false + recipients: + - age1tenantkey... +``` + +## 3. Delta mechanics + +Delta bundles reference a previous full or delta run via `baseExportId` and `baseManifestDigest`. They contain: + +``` +delta/ + changed/ + data/raw/advisories/*.jsonl.zst + ... + removed/ + advisories.jsonl # list of advisory IDs removed + vex.jsonl + sboms.jsonl + manifest.diff.json # summary of counts, hashes, base export metadata +``` + +- **Base lookup:** The worker verifies that the base export is reachable (download path or OCI reference). If missing, the run fails with `ERR_EXPORT_BASE_MISSING`. +- **Change detection:** Uses deterministic hashing of normalized records to compute additions/updates. Indexes are regenerated only for affected subjects. +- **Application order:** Consumers apply deltas sequentially. A `resetBaseline=true` flag instructs them to drop cached state and apply the bundle as a full refresh. + +Example `manifest.diff.json` (delta): + +```json +{ + "baseExportId": "run-20251025-01", + "baseManifestDigest": "sha256:aa11...", + "resetBaseline": false, + "added": { + "advisories": 43, + "vex": 12, + "sboms": 5 + }, + "changed": { + "advisories": 18, + "vex": 7 + }, + "removed": { + "advisories": 2, + "vex": 0, + "sboms": 0 + } +} +``` + +## 4. Encryption workflow + +Mirror bundles support optional encryption of the `data/` subtree: + +- **Algorithm:** Age (X25519) or AES-GCM (256-bit) based on profile configuration. +- **Key wrapping:** Keys fetched from Authority-managed KMS through Export Center. Wrapped data keys stored in `provenance.json` under `encryption.recipients[]`. +- **Metadata:** `manifest.yaml` records `encryption.mode`, `recipients`, and `encryptedPaths`. +- **Strict mode:** `strict=true` encrypts everything except `manifest.yaml` and `export.json`. Default (`false`) leaves manifests unencrypted to simplify discovery. +- **Verification:** CLI (`stella export verify`) and Offline Kit scripts perform signature checks prior to decryption. + +Operators must distribute recipient keys out of band. Export Center does not transmit private keys. + +## 5. Import workflow + +### 5.1 Offline Kit + +Offline Kit bundles reference the latest full mirror export plus the last `N` deltas. Administrators run: + +``` +./offline-kit/bin/mirror import /path/to/mirror-20251029-full.tar.zst +./offline-kit/bin/mirror import /path/to/mirror-20251030-delta.tar.zst +``` + +The tool verifies signatures, applies deltas, and updates the mirror index served by the local gateway. + +### 5.2 Custom automation + +1. Download bundle (`stella export download`) and verify signatures (`stella export verify`). +2. Extract archive into a staging directory. +3. For encrypted bundles, decrypt using the provided age/AES key. +4. Sync `mirror/data` onto the target mirror store (object storage, NFS, etc.). +5. Republish indexes or reload services that depend on the mirror. + +Delta consumers must track `appliedExportIds` to ensure ordering. + +Sequence diagram of download/import: + +```mermaid +sequenceDiagram + participant CLI as stella CLI + participant Mirror as Mirror Store + participant Verify as Verification Tool + CLI->>CLI: stella export download run-20251029-01 + CLI->>Verify: stella export verify run-20251029-01 + CLI->>Mirror: mirror import mirror-20251029-full.tar.zst + CLI->>Mirror: mirror import mirror-20251030-delta.tar.zst + Mirror-->>CLI: import complete (run-20251030-02) +``` + +## 6. Operational guidance + +- **Retention:** Keep at least one full bundle plus the deltas required for disaster recovery. Configure `ExportCenter:Retention:Mirror` to prune older bundles automatically. +- **Storage footprint:** Full bundles can exceed tens of gigabytes. Plan object storage or NAS capacity accordingly and enable compression (`compression.codec=zstd`). +- **Scheduling:** For high-churn environments, run daily full exports and hourly deltas. Record cadence in `manifest.yaml` (`schedule.cron`). +- **Incident recovery:** To rebuild a mirror: + 1. Apply the most recent full bundle. + 2. Apply deltas in order of `createdAt`. + 3. Re-run integrity checks (`mirror verify `). +- **Audit logging:** Export Center logs `mirror.bundle.created`, `mirror.delta.applied`, and `mirror.encryption.enabled` events. Consume them in the central observability pipeline. + +## 7. Troubleshooting + +| Symptom | Meaning | Action | +|---------|---------|--------| +| `ERR_EXPORT_BASE_MISSING` | Base export not available | Republish base bundle or rebuild as full export. | +| Delta applies but mirror misses entries | Deltas applied out of order | Rebuild from last full bundle and reapply in sequence. | +| Decryption fails | Recipient key mismatch or corrupted bundle | Confirm key distribution and re-download bundle. | +| Verification errors | Signature mismatch | Do not import; regenerate bundle and investigate signing pipeline. | +| Manifest hash mismatch | Files changed after extraction | Re-extract bundle and re-run verification; check storage tampering. | + +## 8. References + +- [Export Center Overview](overview.md) +- [Export Center Architecture](architecture.md) +- [Export Center API reference](api.md) +- [Export Center CLI Guide](cli.md) +- [Concelier mirror runbook](../concelier/operations/mirror.md) +- [Aggregation-Only Contract reference](../../ingestion/aggregation-only-contract.md) + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/operations/export-runbook.md b/docs/modules/export-center/operations/runbook.md similarity index 94% rename from docs/operations/export-runbook.md rename to docs/modules/export-center/operations/runbook.md index 168dd10d..5802a37c 100644 --- a/docs/operations/export-runbook.md +++ b/docs/modules/export-center/operations/runbook.md @@ -1,203 +1,203 @@ -# Export Center Operations Runbook - -> Export Center workers and API are landing across Sprints 35-37. This runbook captures the target operational procedures so DevOps can validate them as each milestone goes live. Update specific commands once `EXPORT-SVC-35-006`, `EXPORT-SVC-36-001..004`, and related CLI tasks ship. - -## 1. Service scope - -The Export Center packages StellaOps evidence and policy overlays into reproducible bundles (JSON, Trivy DB, mirror). Operations owns: - -- Worker scaling, queue management, and distribution storage. -- Monitoring and alerts for run throughput, failures, and verification issues. -- Runbook execution for recovery, retention, and compliance. -- Coordination with DevOps validation (cosign + `trivy module db import` smoke tests). - -Related documentation: - -- `docs/export-center/overview.md` -- `docs/export-center/architecture.md` -- `docs/export-center/profiles.md` -- `docs/export-center/trivy-adapter.md` -- `docs/export-center/mirror-bundles.md` -- `docs/export-center/api.md` -- `docs/export-center/cli.md` - -## 2. Contacts & tooling - -| Area | Owner(s) | Escalation | -|------|----------|------------| -| Export Center service | Exporter Service Guild | `#export-center-ops`, on-call rotation | -| Distribution & CI smoke | DevOps Guild | CI channel, PagerDuty `devops-export` | -| KMS / encryption | Authority Core | `#authority-core` | -| Offline Kit dissemination | Offline Kit Guild | `#offline-kit` | - -Primary tooling: - -- `stella export` CLI (submit, watch, download, verify). -- Export Center API (`/api/export/*`) for automation. -- Grafana dashboards (`Export Center / Run Health`, `Export Center / Distribution`). -- Alertmanager routes (`Export.Center.Failures`, `Export.Center.Verify`). - -## 3. Monitoring & SLOs - -Key metrics (exposed by workers and API): - -| Metric | SLO / Alert | Notes | -|--------|-------------|-------| -| `exporter_run_duration_seconds` | p95 < 300 s (full), < 120 s (delta) | Break down by profile (`profile_kind`). | -| `exporter_run_failures_total` | Alert when > 3 failures/15 min per profile | Include `error_code` label. | -| `exporter_run_bytes_total` | Track growth trends | Helps with storage planning. | -| `exporter_distribution_push_seconds` | p95 < 60 s | Covers OCI/object storage. | -| `exporter_verify_failures_total` | Alert on any non-zero | Raised when cosign/Trivy smoke tests fail. | -| `exporter_retention_pruned_total` | Should increase nightly | Confirms retention job success. | - -Dashboards must include: - -- Run throughput by profile. -- Failure breakdown (adapter, signing, distribution). -- Queue depth and worker concurrency (via Orchestrator metrics). -- Storage consumption (object storage buckets, local staging). - -Alerts (Alertmanager): - -- `ExportCenterRunFailureSpike` - `exporter_run_failures_total` increase rate > 3/15 min. -- `ExportCenterVerifyFailure` - any entry in `exporter_verify_failures_total` > 0. -- `ExportCenterWorkerLag` - queue backlog > threshold for 10 minutes. -- `ExportCenterRetentionStale` - no pruning events in 24 hours. - -## 4. Routine operations - -### 4.1 Daily checklist - -- Review dashboard for run throughput and error classes. -- Confirm CI smoke job (cosign + `trivy module db import`) passed. -- Check storage usage against capacity thresholds. -- Verify retention job executed (look for `exporter_retention_pruned_total` increment). -- Scan logs for `adapter.trivy.unsupported_schema_version` or `mirror.delta.apply_failed`. - -### 4.2 Weekly tasks - -- Rotate Download/OCI API tokens if configured with short-lived credentials. -- Review upcoming profile changes (new tenants, profile updates). -- Test `stella export verify` against a recent run for each profile. -- Exercise failover of workers (scale to zero one replica, ensure others pick up). - -### 4.3 Pre-release - -- Ensure bundles generated for release candidates pass cosign verification. -- Capture sample manifests (`export.json`, `manifest.yaml`) for documentation archives. -- Validate Offline Kit packaging includes latest full + delta mirror bundles. - -## 5. Capacity & scaling - -### 5.1 Worker sizing - -- Default workers handle ~2 full runs or 6 delta runs concurrently per 4 vCPU. -- Scale out when: - - Queue depth (`exporter_jobs_ready`) > 10 for 10 minutes. - - p95 durations exceed SLO for multiple runs without failures. -- Use Orchestrator quotas: ensure per-tenant concurrency (`max_active_runs`) is tuned. - -### 5.2 Storage planning - -- Staging storage (object store or filesystem) must hold at least: - - Latest full bundle per tenant per profile. - - Last `N` deltas (default N=5). -- Set retention policy via configuration: - -```yaml -ExportCenter: - Retention: - Mirror: - Mode: days - Value: 30 - Trivy: - Mode: count - Value: 10 -``` - -- Monitor `exporter_storage_bytes_total` (if available) or use bucket metrics from storage provider. - -## 6. Failure response - -| Symptom | Likely cause | Immediate action | Follow-up | -|---------|--------------|------------------|-----------| -| `ERR_EXPORT_UNSUPPORTED_SCHEMA` | Trivy schema mismatch | Pin `SchemaVersion` to previous value; rerun export | Coordinate with Exporter Guild to add new mapping | -| `ERR_EXPORT_BASE_MISSING` | Base manifest unavailable | Trigger full export (`mirror:full`), notify tenant | Investigate storage retention settings | -| Run stuck in `pending` | Worker unavailable / queue paused | Check worker pods / Orchestrator status | Scale workers or fix queue | -| Signing failure (`errorCode=signing`) | KMS outage or permission change | Verify KMS health; retry run; escalate to Authority | Document incident, review key rotation schedule | -| Distribution failure (`errorCode=distribution`) | OCI/object store outage | Switch profile distribution to download-only (`distribution: ["http"]`) | Restore distribution backend, resume normal config | -| CLI verification failure in CI | New bundle did not pass cosign or Trivy import | Inspect pipeline logs; download bundle; rerun verification manually | Engage Exporter Guild if data quality issue | -| Retention job skipped | Scheduler failure or misconfiguration | Run retention job manually (`stella export retention run`) | Audit scheduler configuration | - -Log locations: `exporter` service emits structured logs with `runId`, `profile`, `errorCode`. For Kubernetes deployments, check `kubectl logs deployment/export-center-worker`. - -## 7. Recovery playbooks - -### 7.1 Replaying a failed run - -1. Identify run (`runId`) and root cause via `GET /api/export/runs/{id}`. -2. If configuration changed, clone profile and adjust settings. -3. Resubmit run (`stella export run submit` or API) with `--allow-empty` if intentionally empty. -4. Monitor SSE stream or `stella export run watch`. -5. After success, prune failed run data if necessary. - -### 7.2 Restoring from previous full bundle - -1. Locate last successful full bundle (`mirror:full`) and associated manifest. -2. Download and verify signatures. -3. Extract into mirror staging area. -4. Apply subsequent delta bundles in order. -5. Trigger mirror verification script (`mirror verify `). - -### 7.3 KMS outage response - -1. Disable new export submissions temporarily (set per-tenant quota to 0). -2. Coordinate with Authority Core to restore KMS. -3. Once KMS back, run `stella export run submit --profile --selectors ... --priority catch-up` for affected tenants. - -## 8. Verification workflow - -All bundles must pass both signature and content verification. - -### 8.1 Trivy bundle validation (CI job) - -```bash -cosign verify-blob \ - --key tenants/acme/export-center.pub \ - --signature signatures/trivy-db.sig \ - trivy/db.bundle - -trivy module db import trivy/db.bundle --cache-dir /tmp/trivy-cache -``` - -Automation: `DEVOPS-EXPORT-36-001` ensures this runs on every pipeline. - -### 8.2 Mirror bundle validation - -```bash -cosign verify-blob \ - --key tenants/acme/export-center.pub \ - --signature signatures/export.sig \ - mirror/export.json - -./offline-kit/bin/mirror verify mirror-20251029-full.tar.zst -``` - -If encryption enabled, decrypt using age or AES key before verification. - -## 9. Change management - -- Profile changes require change record referencing tenant impact and expected bundle size. -- Distribution configuration updates (`OCI` vs `HTTP`) must be tested in staging. -- Schema upgrades (e.g., Trivy schema v3) need coordination with DevOps, Exporter, and Docs. -- Update runbook and related docs when processes change (tie updates to `DOCS-EXPORT-37-005`). - -## 10. References - -- `docs/export-center/trivy-adapter.md` -- `docs/export-center/mirror-bundles.md` -- `ops/devops/TASKS.md` (`DEVOPS-EXPORT-36-001`, `DEVOPS-EXPORT-37-001`) -- `docs/ingestion/aggregation-only-contract.md` -- `docs/24_OFFLINE_KIT.md` - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center Operations Runbook + +> Export Center workers and API are landing across Sprints 35-37. This runbook captures the target operational procedures so DevOps can validate them as each milestone goes live. Update specific commands once `EXPORT-SVC-35-006`, `EXPORT-SVC-36-001..004`, and related CLI tasks ship. + +## 1. Service scope + +The Export Center packages StellaOps evidence and policy overlays into reproducible bundles (JSON, Trivy DB, mirror). Operations owns: + +- Worker scaling, queue management, and distribution storage. +- Monitoring and alerts for run throughput, failures, and verification issues. +- Runbook execution for recovery, retention, and compliance. +- Coordination with DevOps validation (cosign + `trivy module db import` smoke tests). + +Related documentation: + +- `docs/modules/export-center/overview.md` +- `docs/modules/export-center/architecture.md` +- `docs/modules/export-center/profiles.md` +- `docs/modules/export-center/trivy-adapter.md` +- `docs/modules/export-center/mirror-bundles.md` +- `docs/modules/export-center/api.md` +- `docs/modules/export-center/cli.md` + +## 2. Contacts & tooling + +| Area | Owner(s) | Escalation | +|------|----------|------------| +| Export Center service | Exporter Service Guild | `#export-center-ops`, on-call rotation | +| Distribution & CI smoke | DevOps Guild | CI channel, PagerDuty `devops-export` | +| KMS / encryption | Authority Core | `#authority-core` | +| Offline Kit dissemination | Offline Kit Guild | `#offline-kit` | + +Primary tooling: + +- `stella export` CLI (submit, watch, download, verify). +- Export Center API (`/api/export/*`) for automation. +- Grafana dashboards (`Export Center / Run Health`, `Export Center / Distribution`). +- Alertmanager routes (`Export.Center.Failures`, `Export.Center.Verify`). + +## 3. Monitoring & SLOs + +Key metrics (exposed by workers and API): + +| Metric | SLO / Alert | Notes | +|--------|-------------|-------| +| `exporter_run_duration_seconds` | p95 < 300 s (full), < 120 s (delta) | Break down by profile (`profile_kind`). | +| `exporter_run_failures_total` | Alert when > 3 failures/15 min per profile | Include `error_code` label. | +| `exporter_run_bytes_total` | Track growth trends | Helps with storage planning. | +| `exporter_distribution_push_seconds` | p95 < 60 s | Covers OCI/object storage. | +| `exporter_verify_failures_total` | Alert on any non-zero | Raised when cosign/Trivy smoke tests fail. | +| `exporter_retention_pruned_total` | Should increase nightly | Confirms retention job success. | + +Dashboards must include: + +- Run throughput by profile. +- Failure breakdown (adapter, signing, distribution). +- Queue depth and worker concurrency (via Orchestrator metrics). +- Storage consumption (object storage buckets, local staging). + +Alerts (Alertmanager): + +- `ExportCenterRunFailureSpike` - `exporter_run_failures_total` increase rate > 3/15 min. +- `ExportCenterVerifyFailure` - any entry in `exporter_verify_failures_total` > 0. +- `ExportCenterWorkerLag` - queue backlog > threshold for 10 minutes. +- `ExportCenterRetentionStale` - no pruning events in 24 hours. + +## 4. Routine operations + +### 4.1 Daily checklist + +- Review dashboard for run throughput and error classes. +- Confirm CI smoke job (cosign + `trivy module db import`) passed. +- Check storage usage against capacity thresholds. +- Verify retention job executed (look for `exporter_retention_pruned_total` increment). +- Scan logs for `adapter.trivy.unsupported_schema_version` or `mirror.delta.apply_failed`. + +### 4.2 Weekly tasks + +- Rotate Download/OCI API tokens if configured with short-lived credentials. +- Review upcoming profile changes (new tenants, profile updates). +- Test `stella export verify` against a recent run for each profile. +- Exercise failover of workers (scale to zero one replica, ensure others pick up). + +### 4.3 Pre-release + +- Ensure bundles generated for release candidates pass cosign verification. +- Capture sample manifests (`export.json`, `manifest.yaml`) for documentation archives. +- Validate Offline Kit packaging includes latest full + delta mirror bundles. + +## 5. Capacity & scaling + +### 5.1 Worker sizing + +- Default workers handle ~2 full runs or 6 delta runs concurrently per 4 vCPU. +- Scale out when: + - Queue depth (`exporter_jobs_ready`) > 10 for 10 minutes. + - p95 durations exceed SLO for multiple runs without failures. +- Use Orchestrator quotas: ensure per-tenant concurrency (`max_active_runs`) is tuned. + +### 5.2 Storage planning + +- Staging storage (object store or filesystem) must hold at least: + - Latest full bundle per tenant per profile. + - Last `N` deltas (default N=5). +- Set retention policy via configuration: + +```yaml +ExportCenter: + Retention: + Mirror: + Mode: days + Value: 30 + Trivy: + Mode: count + Value: 10 +``` + +- Monitor `exporter_storage_bytes_total` (if available) or use bucket metrics from storage provider. + +## 6. Failure response + +| Symptom | Likely cause | Immediate action | Follow-up | +|---------|--------------|------------------|-----------| +| `ERR_EXPORT_UNSUPPORTED_SCHEMA` | Trivy schema mismatch | Pin `SchemaVersion` to previous value; rerun export | Coordinate with Exporter Guild to add new mapping | +| `ERR_EXPORT_BASE_MISSING` | Base manifest unavailable | Trigger full export (`mirror:full`), notify tenant | Investigate storage retention settings | +| Run stuck in `pending` | Worker unavailable / queue paused | Check worker pods / Orchestrator status | Scale workers or fix queue | +| Signing failure (`errorCode=signing`) | KMS outage or permission change | Verify KMS health; retry run; escalate to Authority | Document incident, review key rotation schedule | +| Distribution failure (`errorCode=distribution`) | OCI/object store outage | Switch profile distribution to download-only (`distribution: ["http"]`) | Restore distribution backend, resume normal config | +| CLI verification failure in CI | New bundle did not pass cosign or Trivy import | Inspect pipeline logs; download bundle; rerun verification manually | Engage Exporter Guild if data quality issue | +| Retention job skipped | Scheduler failure or misconfiguration | Run retention job manually (`stella export retention run`) | Audit scheduler configuration | + +Log locations: `exporter` service emits structured logs with `runId`, `profile`, `errorCode`. For Kubernetes deployments, check `kubectl logs deployment/export-center-worker`. + +## 7. Recovery playbooks + +### 7.1 Replaying a failed run + +1. Identify run (`runId`) and root cause via `GET /api/export/runs/{id}`. +2. If configuration changed, clone profile and adjust settings. +3. Resubmit run (`stella export run submit` or API) with `--allow-empty` if intentionally empty. +4. Monitor SSE stream or `stella export run watch`. +5. After success, prune failed run data if necessary. + +### 7.2 Restoring from previous full bundle + +1. Locate last successful full bundle (`mirror:full`) and associated manifest. +2. Download and verify signatures. +3. Extract into mirror staging area. +4. Apply subsequent delta bundles in order. +5. Trigger mirror verification script (`mirror verify `). + +### 7.3 KMS outage response + +1. Disable new export submissions temporarily (set per-tenant quota to 0). +2. Coordinate with Authority Core to restore KMS. +3. Once KMS back, run `stella export run submit --profile --selectors ... --priority catch-up` for affected tenants. + +## 8. Verification workflow + +All bundles must pass both signature and content verification. + +### 8.1 Trivy bundle validation (CI job) + +```bash +cosign verify-blob \ + --key tenants/acme/export-center.pub \ + --signature signatures/trivy-db.sig \ + trivy/db.bundle + +trivy module db import trivy/db.bundle --cache-dir /tmp/trivy-cache +``` + +Automation: `DEVOPS-EXPORT-36-001` ensures this runs on every pipeline. + +### 8.2 Mirror bundle validation + +```bash +cosign verify-blob \ + --key tenants/acme/export-center.pub \ + --signature signatures/export.sig \ + mirror/export.json + +./offline-kit/bin/mirror verify mirror-20251029-full.tar.zst +``` + +If encryption enabled, decrypt using age or AES key before verification. + +## 9. Change management + +- Profile changes require change record referencing tenant impact and expected bundle size. +- Distribution configuration updates (`OCI` vs `HTTP`) must be tested in staging. +- Schema upgrades (e.g., Trivy schema v3) need coordination with DevOps, Exporter, and Docs. +- Update runbook and related docs when processes change (tie updates to `DOCS-EXPORT-37-005`). + +## 10. References + +- `docs/modules/export-center/trivy-adapter.md` +- `docs/modules/export-center/mirror-bundles.md` +- `ops/devops/TASKS.md` (`DEVOPS-EXPORT-36-001`, `DEVOPS-EXPORT-37-001`) +- `docs/ingestion/aggregation-only-contract.md` +- `docs/24_OFFLINE_KIT.md` + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/export-center/overview.md b/docs/modules/export-center/overview.md similarity index 92% rename from docs/export-center/overview.md rename to docs/modules/export-center/overview.md index 3e48412b..723bf153 100644 --- a/docs/export-center/overview.md +++ b/docs/modules/export-center/overview.md @@ -1,63 +1,63 @@ -# Export Center Overview - -The Export Center packages StellaOps evidence and policy outputs into portable, verifiable bundles. It provides one workflow for operators to deliver advisories, SBOMs, VEX statements, and policy decisions into downstream systems or air-gapped environments without rewriting data or violating the Aggregation-Only Contract (AOC). - -## What the Export Center delivers -- **Unified export service.** A dedicated `exporter` service coordinates profiles, runs, signing, and distribution targets with deterministic manifests. -- **Profile catalogue.** Out of the box variants include `json:raw`, `json:policy`, `trivy:db`, `trivy:java-db`, `mirror:full`, and `mirror:delta`, each aligned with AOC rules and downstream compatibility requirements. -- **Surface parity.** Operators can create, monitor, and download exports through the Web API gateway, Console workflows, and the CLI (`stella export ...`). All surfaces enforce tenant scope and RBAC consistently. -- **Automation hooks.** One-off, cron, and event triggers are orchestrated via the Scheduler/Orchestrator integration. Export telemetry (durations, bundle size, verification outcomes) feeds structured logs, metrics, and optional OpenTelemetry traces. - -### Profile variants at a glance - -| Profile | Contents | Primary scenarios | Distribution defaults | -|---------|----------|-------------------|-----------------------| -| `json:raw` | Canonical advisories, VEX, SBOM JSONL with hashes | Downstream analytics, evidence escrow | HTTP download, object storage | -| `json:policy` | `json:raw` plus policy snapshot, evaluated findings | Policy attestation, audit packages | HTTP download, object storage | -| `trivy:db` / `trivy:java-db` | Trivy-compatible vulnerability databases | Feed external scanners and CI | OCI artifact push, download | -| `mirror:full` | Complete evidence, indexes, policy, provenance | Air-gap mirror, disaster recovery | Filesystem bundle, OCI artifact | -| `mirror:delta` | Changes relative to prior manifest | Incremental updates to mirrors | Filesystem bundle, OCI artifact | - -## How it works end-to-end -1. **Profile & scope resolution.** A profile defines export type, content filters, and bundle settings. Scope selectors target tenants, artifacts, time windows, ecosystems, or SBOM subjects. -2. **Ledger collection.** Workers stream canonical data from Findings Ledger, VEX Lens, Conseiller feeds, and SBOM service. Policy exports pin a deterministic policy snapshot from Policy Engine. -3. **Adapter execution.** JSON adapters produce normalized `.jsonl.zst` outputs, Trivy adapters translate to the Trivy DB schema, and mirror adapters build filesystem or OCI bundle layouts. -4. **Manifesting & provenance.** Every run emits `export.json` (profile, filters, counts, checksums) and `provenance.json` (source artifacts, policy snapshot ids, signature references). -5. **Signing & distribution.** Bundles are signed via configured KMS (cosign-compatible) and distributed through HTTP streaming, OCI registry pushes, or object storage staging. - -Refer to `docs/export-center/architecture.md` (Sprint 35 task) for component diagrams and adapter internals once published. - -## Security and compliance guardrails -- **AOC alignment.** Exports bundle raw evidence and optional policy evaluations without mutating source content. Policy overlays remain attributed to Policy Engine and are clearly partitioned. -- **Tenant isolation.** All queries, manifests, and bundle paths carry tenant identifiers. Cross-tenant exports require explicit signed approval and ship with provenance trails. -- **Signing and encryption.** Manifests and payloads are signed using the platform KMS. Mirror profiles support optional in-bundle encryption (age/AES-GCM) with key wrapping. -- **Determinism.** Identical inputs yield identical bundles. Timestamps serialize in UTC ISO-8601; manifests include content hashes for audit replay. - -See `docs/security/policy-governance.md` and `docs/ingestion/aggregation-only-contract.md` for broader guardrail context. - -## Operating it offline -- **Offline Kit integration.** Air-gapped deployments receive pre-built export profiles and object storage layout templates through the Offline Kit bundles. -- **Mirror bundles.** `mirror:full` packages raw evidence, normalized indexes, policy snapshots, and provenance in a portable filesystem layout suitable for disconnected environments. `mirror:delta` tracks changes relative to a prior export manifest. -- **No unsanctioned egress.** The exporter respects the platform allowlist. External calls (e.g., OCI pushes) require explicit configuration and are disabled by default for offline installs. - -Consult `docs/24_OFFLINE_KIT.md` for Offline Kit delivery and `docs/ops/concelier-mirror-operations.md` for mirror ingestion procedures. - -## Getting started -1. **Choose a profile.** Map requirements to the profile table above. Policy-aware exports need a published policy snapshot. -2. **Define selectors.** Decide on tenants, products, SBOM subjects, or time windows to include. Default selectors export the entire tenant scope. -3. **Run via preferred surface.** - - **Console:** Navigate to the Export Center view, create a run, monitor progress, and download artifacts. - - **CLI:** Use `stella export run --profile --selector ` to submit a job, then `stella export download`. - - **API:** POST to `/api/export/runs` with profile id and scope payload; stream results from `/api/export/runs/{id}/download`. -4. **Verify bundles.** Use the attached provenance manifest and cosign signature to validate contents before distributing downstream. - -Refer to `docs/export-center/cli.md` for detailed command syntax and automation examples. - -## Observability & troubleshooting -- Structured logs emit lifecycle events (`fetch`, `adapter`, `sign`, `publish`) with correlation IDs for parallel job tracing. -- Metrics `exporter_run_duration_seconds`, `exporter_bundle_bytes_total`, and `exporter_run_failures_total` feed Grafana dashboards defined in the deployment runbooks. -- Verification failures or schema mismatches bubble up through failure events and appear in Console/CLI with actionable error messages. Inspect the run's audit log and `provenance.json` for root cause. - -See `docs/observability/policy.md` and `docs/ops/deployment-upgrade-runbook.md` for telemetry and operations guidance. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center Overview + +The Export Center packages StellaOps evidence and policy outputs into portable, verifiable bundles. It provides one workflow for operators to deliver advisories, SBOMs, VEX statements, and policy decisions into downstream systems or air-gapped environments without rewriting data or violating the Aggregation-Only Contract (AOC). + +## What the Export Center delivers +- **Unified export service.** A dedicated `exporter` service coordinates profiles, runs, signing, and distribution targets with deterministic manifests. +- **Profile catalogue.** Out of the box variants include `json:raw`, `json:policy`, `trivy:db`, `trivy:java-db`, `mirror:full`, and `mirror:delta`, each aligned with AOC rules and downstream compatibility requirements. +- **Surface parity.** Operators can create, monitor, and download exports through the Web API gateway, Console workflows, and the CLI (`stella export ...`). All surfaces enforce tenant scope and RBAC consistently. +- **Automation hooks.** One-off, cron, and event triggers are orchestrated via the Scheduler/Orchestrator integration. Export telemetry (durations, bundle size, verification outcomes) feeds structured logs, metrics, and optional OpenTelemetry traces. + +### Profile variants at a glance + +| Profile | Contents | Primary scenarios | Distribution defaults | +|---------|----------|-------------------|-----------------------| +| `json:raw` | Canonical advisories, VEX, SBOM JSONL with hashes | Downstream analytics, evidence escrow | HTTP download, object storage | +| `json:policy` | `json:raw` plus policy snapshot, evaluated findings | Policy attestation, audit packages | HTTP download, object storage | +| `trivy:db` / `trivy:java-db` | Trivy-compatible vulnerability databases | Feed external scanners and CI | OCI artifact push, download | +| `mirror:full` | Complete evidence, indexes, policy, provenance | Air-gap mirror, disaster recovery | Filesystem bundle, OCI artifact | +| `mirror:delta` | Changes relative to prior manifest | Incremental updates to mirrors | Filesystem bundle, OCI artifact | + +## How it works end-to-end +1. **Profile & scope resolution.** A profile defines export type, content filters, and bundle settings. Scope selectors target tenants, artifacts, time windows, ecosystems, or SBOM subjects. +2. **Ledger collection.** Workers stream canonical data from Findings Ledger, VEX Lens, Conseiller feeds, and SBOM service. Policy exports pin a deterministic policy snapshot from Policy Engine. +3. **Adapter execution.** JSON adapters produce normalized `.jsonl.zst` outputs, Trivy adapters translate to the Trivy DB schema, and mirror adapters build filesystem or OCI bundle layouts. +4. **Manifesting & provenance.** Every run emits `export.json` (profile, filters, counts, checksums) and `provenance.json` (source artifacts, policy snapshot ids, signature references). +5. **Signing & distribution.** Bundles are signed via configured KMS (cosign-compatible) and distributed through HTTP streaming, OCI registry pushes, or object storage staging. + +Refer to `docs/modules/export-center/architecture.md` (Sprint 35 task) for component diagrams and adapter internals once published. + +## Security and compliance guardrails +- **AOC alignment.** Exports bundle raw evidence and optional policy evaluations without mutating source content. Policy overlays remain attributed to Policy Engine and are clearly partitioned. +- **Tenant isolation.** All queries, manifests, and bundle paths carry tenant identifiers. Cross-tenant exports require explicit signed approval and ship with provenance trails. +- **Signing and encryption.** Manifests and payloads are signed using the platform KMS. Mirror profiles support optional in-bundle encryption (age/AES-GCM) with key wrapping. +- **Determinism.** Identical inputs yield identical bundles. Timestamps serialize in UTC ISO-8601; manifests include content hashes for audit replay. + +See `docs/security/policy-governance.md` and `docs/ingestion/aggregation-only-contract.md` for broader guardrail context. + +## Operating it offline +- **Offline Kit integration.** Air-gapped deployments receive pre-built export profiles and object storage layout templates through the Offline Kit bundles. +- **Mirror bundles.** `mirror:full` packages raw evidence, normalized indexes, policy snapshots, and provenance in a portable filesystem layout suitable for disconnected environments. `mirror:delta` tracks changes relative to a prior export manifest. +- **No unsanctioned egress.** The exporter respects the platform allowlist. External calls (e.g., OCI pushes) require explicit configuration and are disabled by default for offline installs. + +Consult `docs/24_OFFLINE_KIT.md` for Offline Kit delivery and `docs/modules/concelier/operations/mirror.md` for mirror ingestion procedures. + +## Getting started +1. **Choose a profile.** Map requirements to the profile table above. Policy-aware exports need a published policy snapshot. +2. **Define selectors.** Decide on tenants, products, SBOM subjects, or time windows to include. Default selectors export the entire tenant scope. +3. **Run via preferred surface.** + - **Console:** Navigate to the Export Center view, create a run, monitor progress, and download artifacts. + - **CLI:** Use `stella export run --profile --selector ` to submit a job, then `stella export download`. + - **API:** POST to `/api/export/runs` with profile id and scope payload; stream results from `/api/export/runs/{id}/download`. +4. **Verify bundles.** Use the attached provenance manifest and cosign signature to validate contents before distributing downstream. + +Refer to `docs/modules/export-center/cli.md` for detailed command syntax and automation examples. + +## Observability & troubleshooting +- Structured logs emit lifecycle events (`fetch`, `adapter`, `sign`, `publish`) with correlation IDs for parallel job tracing. +- Metrics `exporter_run_duration_seconds`, `exporter_bundle_bytes_total`, and `exporter_run_failures_total` feed Grafana dashboards defined in the deployment runbooks. +- Verification failures or schema mismatches bubble up through failure events and appear in Console/CLI with actionable error messages. Inspect the run's audit log and `provenance.json` for root cause. + +See `docs/observability/policy.md` and `docs/modules/devops/runbooks/deployment-upgrade.md` for telemetry and operations guidance. + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/export-center/profiles.md b/docs/modules/export-center/profiles.md similarity index 94% rename from docs/export-center/profiles.md rename to docs/modules/export-center/profiles.md index 4b0f91a8..1d8f607a 100644 --- a/docs/export-center/profiles.md +++ b/docs/modules/export-center/profiles.md @@ -1,139 +1,139 @@ -# Export Center Profiles - -Export Center profiles define what data is collected, how it is encoded, and which distribution paths are enabled for a run. Profiles are tenant-scoped and deterministic: identical selectors and source data produce identical bundles. This guide summarises built-in profiles, configuration fields, schema conventions, and compatibility notes. - -## Profile catalogue - -| Profile | Kind / Variant | Output artefacts | Primary use cases | -|---------|----------------|------------------|-------------------| -| `json:raw` | `json` / `raw` | Canonical JSONL archives of advisories, VEX, SBOMs | Evidence escrow, analytics pipelines | -| `json:policy` | `json` / `policy` | `json:raw` artefacts plus policy snapshot + evaluated findings | Audit, compliance attestations | -| `trivy:db` | `trivy` / `db` | Trivy-compatible vulnerability database | Feeding external scanners / CI | -| `trivy:java-db` | `trivy` / `java-db` | Java ecosystem supplement for Trivy | Supply Java CVE data to Trivy | -| `mirror:full` | `mirror` / `full` | Complete mirror bundle (raw, policy, indexes, provenance) | Air-gap deployments, disaster recovery | -| `mirror:delta` | `mirror` / `delta` | Incremental changes relative to a prior manifest | Efficient mirror updates | - -Profiles can be cloned and customised; configuration is immutable per revision to keep runs reproducible. - -## Common configuration fields - -| Field | Description | Applies to | Notes | -|-------|-------------|------------|-------| -| `name` | Human-readable identifier displayed in Console/CLI | All | Unique per tenant. | -| `kind` | Logical family (`json`, `trivy`, `mirror`) | All | Determines eligible adapters. | -| `variant` | Specific export flavour (see table above) | All | Controls adapter behaviour. | -| `include` | Record types to include (`advisories`, `vex`, `sboms`, `findings`) | JSON, mirror | Defaults depend on variant. | -| `policySnapshotMode` | `required`, `optional`, or `none` | JSON policy, mirror | `required` forces a policy snapshot id when creating runs. | -| `distribution` | Enabled distribution drivers (`http`, `oci`, `object`) | All | Offline installs typically disable `oci`. | -| `compression` | Compression settings (`zstd`, level) | JSON, mirror | Trivy adapters manage compression internally. | -| `encryption` | Mirror encryption options (`enabled`, `recipientKeys`, `strict`) | Mirror | When enabled, only `/data` subtree is encrypted; manifests remain plaintext. | -| `retention` | Retention policy (days or `never`) | All | Drives pruning jobs for staged bundles. | - -Selectors (time windows, tenants, products, SBOM subjects, ecosystems) are supplied per run, not stored in the profile. - -## JSON profiles - -### `json:raw` -- **Content:** Exports raw advisories, VEX statements, and SBOMs as newline-delimited JSON (`.jsonl.zst`). -- **Schema:** Follows canonical StellaOps schema with casing and timestamps normalised. Each record includes `tenant`, `source`, `linkset`, and `content` fields. -- **Options:** - - `include` defaults to `["advisories", "vex", "sboms"]`. - - `compression` defaults to `zstd` level 9. - - `maxRecordsPerFile` (optional) splits outputs for large datasets. -- **Compatibility:** Intended for analytics platforms, data escrow, or feeding downstream normalisation pipelines. -- **Sample manifest excerpt:** - -```json -{ - "profile": { "kind": "json", "variant": "raw" }, - "outputs": [ - { "type": "advisories.jsonl.zst", "sha256": "...", "count": 15234 }, - { "type": "vex.jsonl.zst", "sha256": "...", "count": 3045 }, - { "type": "sboms.jsonl.zst", "sha256": "...", "count": 872 } - ], - "selectors": { "tenant": "acme", "products": ["registry.example/app"] } -} -``` - -### `json:policy` -- **Content:** Everything from `json:raw` plus: - - `policy_snapshot.json` (policy metadata, version, hash). - - `findings.policy.jsonl.zst` (evaluated findings with decision, rationale, rule id, inputs hash). -- **Determinism:** Requires a policy snapshot id; runs fail if snapshot is missing or non-deterministic mode is active. -- **Use cases:** Compliance exports, auditor packages, policy attestation archives. -- **Guardrails:** AOC boundaries preserved: policy outputs are clearly partitioned from raw evidence. - -## Trivy profiles - -### `trivy:db` -- Detailed adapter behaviour is documented in `docs/export-center/trivy-adapter.md`. -- **Content:** Produces a Trivy DB-compatible bundle (SQLite database or tarball as required by Trivy version). -- **Mapping rules:** - - Advisory namespaces mapped to Trivy vendor IDs (e.g., `ubuntu`, `debian`, `npm`). - - Version ranges translated into Trivy's semantic version syntax. - - Severity mapped to Trivy standard (`UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`). -- **Validation:** Adapter enforces supported Trivy schema versions; configuration includes `targetSchemaVersion`. -- **Distribution:** Typically pushed to OCI or object storage for downstream scanners; Console download remains available. - -### `trivy:java-db` -- Refer to `docs/export-center/trivy-adapter.md` for ecosystem-specific notes. -- **Content:** Optional Java ecosystem supplement for Trivy (matching Trivy's separate Java DB). -- **Dependencies:** Requires Java advisories in Findings Ledger; run fails with `ERR_EXPORT_EMPTY` if no Java data present and `allowEmpty=false`. -- **Compatibility:** Intended for organisations using Trivy's Java plugin or hardened pipelines that split general and Java feeds. - -## Mirror profiles - -### `mirror:full` -- Bundle structure and delta strategy are covered in `docs/export-center/mirror-bundles.md`. -- **Content:** Complete export with: - - Raw advisories, VEX, SBOMs (`/data/raw`). - - Policy overlays (`/data/policy`), including evaluated findings and policy snapshots. - - Indexes for fast lookup (`/indexes/advisories.pb`, `/indexes/sboms.pb`). - - Manifests and provenance (`/manifests/export.json`, `/manifests/provenance.json`). -- **Layout:** Deterministic directory structure with hashed filenames to reduce duplication. -- **Encryption:** Optional `encryption` block enables age/AES-GCM encryption of `/data`. `strict=true` encrypts everything except `export.json`. -- **Use cases:** Air-gap replication, disaster recovery drills, Offline Kit seeding. - -### `mirror:delta` -- See `docs/export-center/mirror-bundles.md` for delta mechanics and application order. -- **Content:** Includes only changes relative to a base manifest (specified by `baseExportId` when running). - - `changed`, `added`, `removed` lists in `manifests/delta.json`. - - Incremental indexes capturing only updated subjects. -- **Constraints:** Requires the base manifest to exist in object storage or artifact registry accessible to the worker. Fails with `ERR_EXPORT_BASE_MISSING` otherwise. -- **Workflow:** Ideal for frequent updates to mirrored environments with limited bandwidth. - -## Compatibility and guardrails -- **Aggregation-Only Contract:** All profiles respect AOC boundaries: raw evidence is never mutated. Policy outputs are appended separately with clear provenance. -- **Tenant scoping:** Profiles are tenant-specific. Cross-tenant exports require explicit administrative approval and signed justification. -- **Retriable runs:** Re-running a profile with identical selectors yields matching manifests and hashes, facilitating verify-on-download workflows. -- **Offline operation:** JSON and mirror profiles function in offline mode without additional configuration. Trivy profiles require pre-seeded schema metadata shipped via Offline Kit. -- **Quota integration:** Profiles can define run quotas (per tenant per day). Quota exhaustion surfaces as `429 Too Many Requests` with `X-Stella-Quota-*` hints. - -## Example profile definition (CLI) - -```jsonc -{ - "name": "daily-json-raw", - "kind": "json", - "variant": "raw", - "include": ["advisories", "vex", "sboms"], - "distribution": ["http", "object"], - "compression": { "codec": "zstd", "level": 9 }, - "retention": { "mode": "days", "value": 14 } -} -``` - -Create via `stella export profile create --file profile.json` (CLI command documented separately). - -## Verification workflow -- Download bundle via Console/CLI and extract `export.json` and `provenance.json`. -- Run `cosign verify --key export.json` (for detatched signatures use `--signature export.json.sig`). -- Validate Trivy bundles with `trivy --cache-dir --debug --db-repository ` or local `trivy module db import`. -- For mirror bundles, run internal `mirror verify` script (bundled in Offline Kit) to ensure directory layout and digests match manifest. - -## Extending profiles -- Use API/CLI to clone an existing profile and adjust `include`, `distribution`, or retention policies. -- Adapter plug-ins can introduce new variants (e.g., `json:raw-lite`, `mirror:policy-only`). Plug-ins must be registered at service restart and documented under `/docs/export-center/profiles.md`. -- Any new profile must append the imposed rule line and follow determinism and guardrail requirements. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center Profiles + +Export Center profiles define what data is collected, how it is encoded, and which distribution paths are enabled for a run. Profiles are tenant-scoped and deterministic: identical selectors and source data produce identical bundles. This guide summarises built-in profiles, configuration fields, schema conventions, and compatibility notes. + +## Profile catalogue + +| Profile | Kind / Variant | Output artefacts | Primary use cases | +|---------|----------------|------------------|-------------------| +| `json:raw` | `json` / `raw` | Canonical JSONL archives of advisories, VEX, SBOMs | Evidence escrow, analytics pipelines | +| `json:policy` | `json` / `policy` | `json:raw` artefacts plus policy snapshot + evaluated findings | Audit, compliance attestations | +| `trivy:db` | `trivy` / `db` | Trivy-compatible vulnerability database | Feeding external scanners / CI | +| `trivy:java-db` | `trivy` / `java-db` | Java ecosystem supplement for Trivy | Supply Java CVE data to Trivy | +| `mirror:full` | `mirror` / `full` | Complete mirror bundle (raw, policy, indexes, provenance) | Air-gap deployments, disaster recovery | +| `mirror:delta` | `mirror` / `delta` | Incremental changes relative to a prior manifest | Efficient mirror updates | + +Profiles can be cloned and customised; configuration is immutable per revision to keep runs reproducible. + +## Common configuration fields + +| Field | Description | Applies to | Notes | +|-------|-------------|------------|-------| +| `name` | Human-readable identifier displayed in Console/CLI | All | Unique per tenant. | +| `kind` | Logical family (`json`, `trivy`, `mirror`) | All | Determines eligible adapters. | +| `variant` | Specific export flavour (see table above) | All | Controls adapter behaviour. | +| `include` | Record types to include (`advisories`, `vex`, `sboms`, `findings`) | JSON, mirror | Defaults depend on variant. | +| `policySnapshotMode` | `required`, `optional`, or `none` | JSON policy, mirror | `required` forces a policy snapshot id when creating runs. | +| `distribution` | Enabled distribution drivers (`http`, `oci`, `object`) | All | Offline installs typically disable `oci`. | +| `compression` | Compression settings (`zstd`, level) | JSON, mirror | Trivy adapters manage compression internally. | +| `encryption` | Mirror encryption options (`enabled`, `recipientKeys`, `strict`) | Mirror | When enabled, only `/data` subtree is encrypted; manifests remain plaintext. | +| `retention` | Retention policy (days or `never`) | All | Drives pruning jobs for staged bundles. | + +Selectors (time windows, tenants, products, SBOM subjects, ecosystems) are supplied per run, not stored in the profile. + +## JSON profiles + +### `json:raw` +- **Content:** Exports raw advisories, VEX statements, and SBOMs as newline-delimited JSON (`.jsonl.zst`). +- **Schema:** Follows canonical StellaOps schema with casing and timestamps normalised. Each record includes `tenant`, `source`, `linkset`, and `content` fields. +- **Options:** + - `include` defaults to `["advisories", "vex", "sboms"]`. + - `compression` defaults to `zstd` level 9. + - `maxRecordsPerFile` (optional) splits outputs for large datasets. +- **Compatibility:** Intended for analytics platforms, data escrow, or feeding downstream normalisation pipelines. +- **Sample manifest excerpt:** + +```json +{ + "profile": { "kind": "json", "variant": "raw" }, + "outputs": [ + { "type": "advisories.jsonl.zst", "sha256": "...", "count": 15234 }, + { "type": "vex.jsonl.zst", "sha256": "...", "count": 3045 }, + { "type": "sboms.jsonl.zst", "sha256": "...", "count": 872 } + ], + "selectors": { "tenant": "acme", "products": ["registry.example/app"] } +} +``` + +### `json:policy` +- **Content:** Everything from `json:raw` plus: + - `policy_snapshot.json` (policy metadata, version, hash). + - `findings.policy.jsonl.zst` (evaluated findings with decision, rationale, rule id, inputs hash). +- **Determinism:** Requires a policy snapshot id; runs fail if snapshot is missing or non-deterministic mode is active. +- **Use cases:** Compliance exports, auditor packages, policy attestation archives. +- **Guardrails:** AOC boundaries preserved: policy outputs are clearly partitioned from raw evidence. + +## Trivy profiles + +### `trivy:db` +- Detailed adapter behaviour is documented in `docs/modules/export-center/trivy-adapter.md`. +- **Content:** Produces a Trivy DB-compatible bundle (SQLite database or tarball as required by Trivy version). +- **Mapping rules:** + - Advisory namespaces mapped to Trivy vendor IDs (e.g., `ubuntu`, `debian`, `npm`). + - Version ranges translated into Trivy's semantic version syntax. + - Severity mapped to Trivy standard (`UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`). +- **Validation:** Adapter enforces supported Trivy schema versions; configuration includes `targetSchemaVersion`. +- **Distribution:** Typically pushed to OCI or object storage for downstream scanners; Console download remains available. + +### `trivy:java-db` +- Refer to `docs/modules/export-center/trivy-adapter.md` for ecosystem-specific notes. +- **Content:** Optional Java ecosystem supplement for Trivy (matching Trivy's separate Java DB). +- **Dependencies:** Requires Java advisories in Findings Ledger; run fails with `ERR_EXPORT_EMPTY` if no Java data present and `allowEmpty=false`. +- **Compatibility:** Intended for organisations using Trivy's Java plugin or hardened pipelines that split general and Java feeds. + +## Mirror profiles + +### `mirror:full` +- Bundle structure and delta strategy are covered in `docs/modules/export-center/mirror-bundles.md`. +- **Content:** Complete export with: + - Raw advisories, VEX, SBOMs (`/data/raw`). + - Policy overlays (`/data/policy`), including evaluated findings and policy snapshots. + - Indexes for fast lookup (`/indexes/advisories.pb`, `/indexes/sboms.pb`). + - Manifests and provenance (`/manifests/export.json`, `/manifests/provenance.json`). +- **Layout:** Deterministic directory structure with hashed filenames to reduce duplication. +- **Encryption:** Optional `encryption` block enables age/AES-GCM encryption of `/data`. `strict=true` encrypts everything except `export.json`. +- **Use cases:** Air-gap replication, disaster recovery drills, Offline Kit seeding. + +### `mirror:delta` +- See `docs/modules/export-center/mirror-bundles.md` for delta mechanics and application order. +- **Content:** Includes only changes relative to a base manifest (specified by `baseExportId` when running). + - `changed`, `added`, `removed` lists in `manifests/delta.json`. + - Incremental indexes capturing only updated subjects. +- **Constraints:** Requires the base manifest to exist in object storage or artifact registry accessible to the worker. Fails with `ERR_EXPORT_BASE_MISSING` otherwise. +- **Workflow:** Ideal for frequent updates to mirrored environments with limited bandwidth. + +## Compatibility and guardrails +- **Aggregation-Only Contract:** All profiles respect AOC boundaries: raw evidence is never mutated. Policy outputs are appended separately with clear provenance. +- **Tenant scoping:** Profiles are tenant-specific. Cross-tenant exports require explicit administrative approval and signed justification. +- **Retriable runs:** Re-running a profile with identical selectors yields matching manifests and hashes, facilitating verify-on-download workflows. +- **Offline operation:** JSON and mirror profiles function in offline mode without additional configuration. Trivy profiles require pre-seeded schema metadata shipped via Offline Kit. +- **Quota integration:** Profiles can define run quotas (per tenant per day). Quota exhaustion surfaces as `429 Too Many Requests` with `X-Stella-Quota-*` hints. + +## Example profile definition (CLI) + +```jsonc +{ + "name": "daily-json-raw", + "kind": "json", + "variant": "raw", + "include": ["advisories", "vex", "sboms"], + "distribution": ["http", "object"], + "compression": { "codec": "zstd", "level": 9 }, + "retention": { "mode": "days", "value": 14 } +} +``` + +Create via `stella export profile create --file profile.json` (CLI command documented separately). + +## Verification workflow +- Download bundle via Console/CLI and extract `export.json` and `provenance.json`. +- Run `cosign verify --key export.json` (for detatched signatures use `--signature export.json.sig`). +- Validate Trivy bundles with `trivy --cache-dir --debug --db-repository ` or local `trivy module db import`. +- For mirror bundles, run internal `mirror verify` script (bundled in Offline Kit) to ensure directory layout and digests match manifest. + +## Extending profiles +- Use API/CLI to clone an existing profile and adjust `include`, `distribution`, or retention policies. +- Adapter plug-ins can introduce new variants (e.g., `json:raw-lite`, `mirror:policy-only`). Plug-ins must be registered at service restart and documented under `/docs/modules/export-center/profiles.md`. +- Any new profile must append the imposed rule line and follow determinism and guardrail requirements. + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/export-center/provenance-and-signing.md b/docs/modules/export-center/provenance-and-signing.md similarity index 97% rename from docs/export-center/provenance-and-signing.md rename to docs/modules/export-center/provenance-and-signing.md index 622694e5..178ef35d 100644 --- a/docs/export-center/provenance-and-signing.md +++ b/docs/modules/export-center/provenance-and-signing.md @@ -1,150 +1,150 @@ -# Export Center Provenance & Signing - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -Export Center runs emit deterministic manifests, provenance records, and signatures so operators can prove bundle integrity end-to-end—whether the artefact is downloaded over HTTPS, pulled as an OCI object, or staged through the Offline Kit. This guide captures the canonical artefacts, signing pipeline, verification workflows, and failure handling expectations that backlogs `EXPORT-SVC-35-005` and `EXPORT-SVC-37-002` implement. - ---- - -## 1. Goals & scope - -- **Authenticity.** Every export manifest and provenance document is signed using Authority-managed KMS keys (cosign-compatible) with optional SLSA Level 3 attestation. -- **Traceability.** Provenance links each bundle to the inputs that produced it: tenant, findings ledger queries, policy snapshots, SBOM identifiers, adapter versions, and encryption recipients. -- **Determinism.** Canonical JSON (sorted keys, RFC 3339 UTC timestamps, normalized numbers) guarantees byte-for-byte stability across reruns with identical input. -- **Portability.** Signatures and attestations travel with filesystem bundles, OCI artefacts, and Offline Kit staging trees. Verification does not require online Authority access when the bundle includes the cosign public key. - ---- - -## 2. Artefact inventory - -| File | Location | Description | Notes | -|------|----------|-------------|-------| -| `export.json` | `manifests/export.json` or HTTP `GET /api/export/runs/{id}/manifest` | Canonical manifest describing profile, selectors, counts, SHA-256 digests, compression hints, distribution targets. | Hash of this file is included in provenance `subjects[]`. | -| `provenance.json` | `manifests/provenance.json` or `GET /api/export/runs/{id}/provenance` | In-toto provenance record listing subjects, materials, toolchain metadata, encryption recipients, and KMS key identifiers. | Mirrors SLSA Level 2 schema; optionally upgraded to Level 3 with builder attestations. | -| `export.json.sig` / `export.json.dsse` | `signatures/export.json.sig` | Cosign signature (and optional DSSE envelope) for manifest. | File naming matches cosign defaults; offline verification scripts expect `.sig`. | -| `provenance.json.sig` / `provenance.json.dsse` | `signatures/provenance.json.sig` | Cosign signature (and optional DSSE envelope) for provenance document. | `dsse` present when SLSA Level 3 is enabled. | -| `bundle.attestation` | `signatures/bundle.attestation` (optional) | SLSA Level 2/3 attestation binding bundle tarball/OCI digest to the run. | Only produced when `export.attestation.enabled=true`. | -| `manifest.yaml` | bundle root | Human-readable summary including digests, sizes, encryption metadata, and verification hints. | Unsigned but redundant; signatures cover the JSON manifests. | - -All digests use lowercase hex SHA-256 (`sha256:`). When bundle encryption is enabled, `provenance.json` records wrapped data keys and recipient fingerprints under `encryption.recipients[]`. - ---- - -## 3. Signing pipeline - -1. **Canonicalisation.** Export worker serialises `export.json` and `provenance.json` using `NotifyCanonicalJsonSerializer` (identical canonical JSON helpers shared across services). Keys are sorted lexicographically, arrays ordered deterministically, timestamps normalised to UTC. -2. **Digest creation.** SHA-256 digests are computed and recorded: - - `manifest_hash` and `provenance_hash` stored in the run metadata (Mongo) and exported via `/api/export/runs/{id}`. - - Provenance `subjects[]` contains both manifest hash and bundle/archive hash. -3. **Key retrieval.** Worker obtains a short-lived signing token from Authority’s KMS client using tenant-scoped credentials (`export.sign` scope). Keys live in Authority or tenant-specific HSMs depending on deployment. -4. **Signature emission.** Cosign generates detached signatures (`*.sig`). If DSSE is enabled, cosign wraps payload bytes in a DSSE envelope (`*.dsse`). Attestations follow the SLSA Level 2 provenance template; Level 3 requires builder metadata (`EXPORT-SVC-37-002` optional feature flag). -5. **Storage & distribution.** Signatures and attestations are written alongside manifests in object storage, included in filesystem bundles, and attached as OCI artefact layers/annotations. -6. **Audit trail.** Run metadata captures signer identity (`signing_key_id`), cosign certificate serial, signature timestamps, and verification hints. Console/CLI surface these details for downstream automation. - -> **Key management.** Secrets and key references are configured per tenant via `export.signing`, pointing to Authority clients or external HSM aliases. Offline deployments pre-load cosign public keys into the bundle (`signatures/pubkeys/{tenant}.pem`). - ---- - -## 4. Provenance schema highlights - -`provenance.json` follows the SLSA provenance (`https://slsa.dev/provenance/v1`) structure with StellaOps-specific extensions. Key fields: - -| Path | Description | -|------|-------------| -| `subject[]` | Array of `{name,digest}` pairs. Includes bundle tarball/OCI digest and `export.json` digest. | -| `predicateType` | SLSA v1 (default). | -| `predicate.builder` | `{id:"stellaops/export-center@"}` identifies the worker instance/cluster. | -| `predicate.buildType` | Profile identifier (`mirror:full`, `mirror:delta`, etc.). | -| `predicate.invocation.parameters` | Profile selectors, retention flags, encryption mode, base export references. | -| `predicate.materials[]` | Source artefacts with digests: findings ledger query snapshots, policy snapshot IDs + hashes, SBOM identifiers, adapter release digests. | -| `predicate.metadata.buildFinishedOn` | RFC 3339 timestamp when signing completed. | -| `predicate.metadata.reproducible` | Always `true`—workers guarantee determinism. | -| `predicate.environment.encryption` | Records encryption recipients, wrapped keys, algorithm (`age` or `aes-gcm`). | -| `predicate.environment.kms` | Signing key identifier (`authority://tenant/export-signing-key`) and certificate chain fingerprints. | - -Sample (abridged): - -```json -{ - "subject": [ - { "name": "bundle.tar.zst", "digest": { "sha256": "c1fe..." } }, - { "name": "manifests/export.json", "digest": { "sha256": "ad42..." } } - ], - "predicate": { - "buildType": "mirror:delta", - "invocation": { - "parameters": { - "tenant": "tenant-01", - "baseExportId": "run-20251020-01", - "selectors": { "sources": ["concelier","vexer"], "profiles": ["mirror"] } - } - }, - "materials": [ - { "uri": "ledger://tenant-01/findings?cursor=rev-42", "digest": { "sha256": "0f9a..." } }, - { "uri": "policy://tenant-01/snapshots/rev-17", "digest": { "sha256": "8c3d..." } } - ], - "environment": { - "encryption": { - "mode": "age", - "recipients": [ - { "recipient": "age1qxyz...", "wrappedKey": "BASE64...", "keyId": "tenant-01/notify-age" } - ] - }, - "kms": { - "signingKeyId": "authority://tenant-01/export-signing", - "certificateChainSha256": "1f5e..." - } - } - } -} -``` - ---- - -## 5. Verification workflows - -| Scenario | Steps | -|----------|-------| -| **CLI verification** | 1. `stella export manifest --output manifests/export.json --signature manifests/export.json.sig`
2. `stella export provenance --output manifests/provenance.json --signature manifests/provenance.json.sig`
3. `cosign verify-blob --key pubkeys/tenant.pem --signature manifests/export.json.sig manifests/export.json`
4. `cosign verify-blob --key pubkeys/tenant.pem --signature manifests/provenance.json.sig manifests/provenance.json` | -| **Bundle verification (offline)** | 1. Extract bundle (or mount OCI artefact).
2. Validate manifest/provenance signatures using bundled public key.
3. Recompute SHA-256 for `data/` files and compare with entries in `export.json`.
4. If encrypted, decrypt with Age/AES-GCM recipient key, then re-run digest comparisons on decrypted content. | -| **CI pipeline** | Use `stella export verify --manifest manifests/export.json --provenance manifests/provenance.json --signature manifests/export.json.sig --signature manifests/provenance.json.sig` (task `CLI-EXPORT-37-001`). Failure exits non-zero with reason codes (`ERR_EXPORT_SIG_INVALID`, `ERR_EXPORT_DIGEST_MISMATCH`). | -| **Console download** | Console automatically verifies signatures before exposing the bundle; failure surfaces an actionable error referencing the export run ID and required remediation. | - -Verification guidance (docs/cli/cli-reference.md §export) cross-links here; keep both docs in sync when CLI behaviour changes. - ---- - -## 6. Distribution considerations - -- **HTTP headers.** `X-Export-Digest` includes bundle digest; `X-Export-Provenance` references `provenance.json` URL; `X-Export-Signature` references `.sig`. Clients use these hints to short-circuit re-downloads. -- **OCI annotations.** `org.opencontainers.image.ref.name`, `io.stellaops.export.manifest-digest`, and `io.stellaops.export.provenance-ref` allow registry tooling to locate manifests/signatures quickly. -- **Offline Kit staging.** Offline kit assembler copies `manifests/`, `signatures/`, and `pubkeys/` verbatim. Verification scripts (`offline-kits/bin/verify-export.sh`) wrap the cosign commands described above. - ---- - -## 7. Failure handling & observability - -- Runs surface signature status via `/api/export/runs/{id}` (`signing.status`, `signing.lastError`). Common errors include `ERR_EXPORT_KMS_UNAVAILABLE`, `ERR_EXPORT_ATTESTATION_FAILED`, `ERR_EXPORT_CANONICALIZE`. -- Metrics: `exporter_sign_duration_seconds`, `exporter_sign_failures_total{error_code}`, `exporter_provenance_verify_failures_total`. -- Logs: `phase=sign`, `error_code`, `signing_key_id`, `cosign_certificate_sn`. -- Alerts: DevOps dashboards (task `DEVOPS-EXPORT-37-001`) trigger on consecutive signing failures or verification failures >0. - -When verification fails downstream, operators should: -1. Confirm signatures using the known-good key. -2. Inspect `provenance.json` materials; rerun the source queries to ensure matching digests. -3. Review run audit logs and retry export with `--resume` to regenerate manifests. - ---- - -## 8. Compliance checklist - -- [ ] Manifests and provenance documents generated with canonical JSON, deterministic digests, and signatures. -- [ ] Cosign public keys published per tenant, rotated through Authority, and distributed to Offline Kit consumers. -- [ ] SLSA attestations enabled where supply-chain requirements demand Level 3 evidence. -- [ ] CLI/Console verification paths documented and tested (CI pipelines exercise `stella export verify`). -- [ ] Encryption metadata (recipients, wrapped keys) recorded in provenance and validated during verification. -- [ ] Run audit logs capture signature timestamps, signer identity, and failure reasons. - ---- - -> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Export Center Provenance & Signing + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +Export Center runs emit deterministic manifests, provenance records, and signatures so operators can prove bundle integrity end-to-end—whether the artefact is downloaded over HTTPS, pulled as an OCI object, or staged through the Offline Kit. This guide captures the canonical artefacts, signing pipeline, verification workflows, and failure handling expectations that backlogs `EXPORT-SVC-35-005` and `EXPORT-SVC-37-002` implement. + +--- + +## 1. Goals & scope + +- **Authenticity.** Every export manifest and provenance document is signed using Authority-managed KMS keys (cosign-compatible) with optional SLSA Level 3 attestation. +- **Traceability.** Provenance links each bundle to the inputs that produced it: tenant, findings ledger queries, policy snapshots, SBOM identifiers, adapter versions, and encryption recipients. +- **Determinism.** Canonical JSON (sorted keys, RFC 3339 UTC timestamps, normalized numbers) guarantees byte-for-byte stability across reruns with identical input. +- **Portability.** Signatures and attestations travel with filesystem bundles, OCI artefacts, and Offline Kit staging trees. Verification does not require online Authority access when the bundle includes the cosign public key. + +--- + +## 2. Artefact inventory + +| File | Location | Description | Notes | +|------|----------|-------------|-------| +| `export.json` | `manifests/export.json` or HTTP `GET /api/export/runs/{id}/manifest` | Canonical manifest describing profile, selectors, counts, SHA-256 digests, compression hints, distribution targets. | Hash of this file is included in provenance `subjects[]`. | +| `provenance.json` | `manifests/provenance.json` or `GET /api/export/runs/{id}/provenance` | In-toto provenance record listing subjects, materials, toolchain metadata, encryption recipients, and KMS key identifiers. | Mirrors SLSA Level 2 schema; optionally upgraded to Level 3 with builder attestations. | +| `export.json.sig` / `export.json.dsse` | `signatures/export.json.sig` | Cosign signature (and optional DSSE envelope) for manifest. | File naming matches cosign defaults; offline verification scripts expect `.sig`. | +| `provenance.json.sig` / `provenance.json.dsse` | `signatures/provenance.json.sig` | Cosign signature (and optional DSSE envelope) for provenance document. | `dsse` present when SLSA Level 3 is enabled. | +| `bundle.attestation` | `signatures/bundle.attestation` (optional) | SLSA Level 2/3 attestation binding bundle tarball/OCI digest to the run. | Only produced when `export.attestation.enabled=true`. | +| `manifest.yaml` | bundle root | Human-readable summary including digests, sizes, encryption metadata, and verification hints. | Unsigned but redundant; signatures cover the JSON manifests. | + +All digests use lowercase hex SHA-256 (`sha256:`). When bundle encryption is enabled, `provenance.json` records wrapped data keys and recipient fingerprints under `encryption.recipients[]`. + +--- + +## 3. Signing pipeline + +1. **Canonicalisation.** Export worker serialises `export.json` and `provenance.json` using `NotifyCanonicalJsonSerializer` (identical canonical JSON helpers shared across services). Keys are sorted lexicographically, arrays ordered deterministically, timestamps normalised to UTC. +2. **Digest creation.** SHA-256 digests are computed and recorded: + - `manifest_hash` and `provenance_hash` stored in the run metadata (Mongo) and exported via `/api/export/runs/{id}`. + - Provenance `subjects[]` contains both manifest hash and bundle/archive hash. +3. **Key retrieval.** Worker obtains a short-lived signing token from Authority’s KMS client using tenant-scoped credentials (`export.sign` scope). Keys live in Authority or tenant-specific HSMs depending on deployment. +4. **Signature emission.** Cosign generates detached signatures (`*.sig`). If DSSE is enabled, cosign wraps payload bytes in a DSSE envelope (`*.dsse`). Attestations follow the SLSA Level 2 provenance template; Level 3 requires builder metadata (`EXPORT-SVC-37-002` optional feature flag). +5. **Storage & distribution.** Signatures and attestations are written alongside manifests in object storage, included in filesystem bundles, and attached as OCI artefact layers/annotations. +6. **Audit trail.** Run metadata captures signer identity (`signing_key_id`), cosign certificate serial, signature timestamps, and verification hints. Console/CLI surface these details for downstream automation. + +> **Key management.** Secrets and key references are configured per tenant via `export.signing`, pointing to Authority clients or external HSM aliases. Offline deployments pre-load cosign public keys into the bundle (`signatures/pubkeys/{tenant}.pem`). + +--- + +## 4. Provenance schema highlights + +`provenance.json` follows the SLSA provenance (`https://slsa.dev/provenance/v1`) structure with StellaOps-specific extensions. Key fields: + +| Path | Description | +|------|-------------| +| `subject[]` | Array of `{name,digest}` pairs. Includes bundle tarball/OCI digest and `export.json` digest. | +| `predicateType` | SLSA v1 (default). | +| `predicate.builder` | `{id:"stellaops/export-center@"}` identifies the worker instance/cluster. | +| `predicate.buildType` | Profile identifier (`mirror:full`, `mirror:delta`, etc.). | +| `predicate.invocation.parameters` | Profile selectors, retention flags, encryption mode, base export references. | +| `predicate.materials[]` | Source artefacts with digests: findings ledger query snapshots, policy snapshot IDs + hashes, SBOM identifiers, adapter release digests. | +| `predicate.metadata.buildFinishedOn` | RFC 3339 timestamp when signing completed. | +| `predicate.metadata.reproducible` | Always `true`—workers guarantee determinism. | +| `predicate.environment.encryption` | Records encryption recipients, wrapped keys, algorithm (`age` or `aes-gcm`). | +| `predicate.environment.kms` | Signing key identifier (`authority://tenant/export-signing-key`) and certificate chain fingerprints. | + +Sample (abridged): + +```json +{ + "subject": [ + { "name": "bundle.tar.zst", "digest": { "sha256": "c1fe..." } }, + { "name": "manifests/export.json", "digest": { "sha256": "ad42..." } } + ], + "predicate": { + "buildType": "mirror:delta", + "invocation": { + "parameters": { + "tenant": "tenant-01", + "baseExportId": "run-20251020-01", + "selectors": { "sources": ["concelier","vexer"], "profiles": ["mirror"] } + } + }, + "materials": [ + { "uri": "ledger://tenant-01/findings?cursor=rev-42", "digest": { "sha256": "0f9a..." } }, + { "uri": "policy://tenant-01/snapshots/rev-17", "digest": { "sha256": "8c3d..." } } + ], + "environment": { + "encryption": { + "mode": "age", + "recipients": [ + { "recipient": "age1qxyz...", "wrappedKey": "BASE64...", "keyId": "tenant-01/notify-age" } + ] + }, + "kms": { + "signingKeyId": "authority://tenant-01/export-signing", + "certificateChainSha256": "1f5e..." + } + } + } +} +``` + +--- + +## 5. Verification workflows + +| Scenario | Steps | +|----------|-------| +| **CLI verification** | 1. `stella export manifest --output manifests/export.json --signature manifests/export.json.sig`
2. `stella export provenance --output manifests/provenance.json --signature manifests/provenance.json.sig`
3. `cosign verify-blob --key pubkeys/tenant.pem --signature manifests/export.json.sig manifests/export.json`
4. `cosign verify-blob --key pubkeys/tenant.pem --signature manifests/provenance.json.sig manifests/provenance.json` | +| **Bundle verification (offline)** | 1. Extract bundle (or mount OCI artefact).
2. Validate manifest/provenance signatures using bundled public key.
3. Recompute SHA-256 for `data/` files and compare with entries in `export.json`.
4. If encrypted, decrypt with Age/AES-GCM recipient key, then re-run digest comparisons on decrypted content. | +| **CI pipeline** | Use `stella export verify --manifest manifests/export.json --provenance manifests/provenance.json --signature manifests/export.json.sig --signature manifests/provenance.json.sig` (task `CLI-EXPORT-37-001`). Failure exits non-zero with reason codes (`ERR_EXPORT_SIG_INVALID`, `ERR_EXPORT_DIGEST_MISMATCH`). | +| **Console download** | Console automatically verifies signatures before exposing the bundle; failure surfaces an actionable error referencing the export run ID and required remediation. | + +Verification guidance (docs/modules/cli/guides/cli-reference.md §export) cross-links here; keep both docs in sync when CLI behaviour changes. + +--- + +## 6. Distribution considerations + +- **HTTP headers.** `X-Export-Digest` includes bundle digest; `X-Export-Provenance` references `provenance.json` URL; `X-Export-Signature` references `.sig`. Clients use these hints to short-circuit re-downloads. +- **OCI annotations.** `org.opencontainers.image.ref.name`, `io.stellaops.export.manifest-digest`, and `io.stellaops.export.provenance-ref` allow registry tooling to locate manifests/signatures quickly. +- **Offline Kit staging.** Offline kit assembler copies `manifests/`, `signatures/`, and `pubkeys/` verbatim. Verification scripts (`offline-kits/bin/verify-export.sh`) wrap the cosign commands described above. + +--- + +## 7. Failure handling & observability + +- Runs surface signature status via `/api/export/runs/{id}` (`signing.status`, `signing.lastError`). Common errors include `ERR_EXPORT_KMS_UNAVAILABLE`, `ERR_EXPORT_ATTESTATION_FAILED`, `ERR_EXPORT_CANONICALIZE`. +- Metrics: `exporter_sign_duration_seconds`, `exporter_sign_failures_total{error_code}`, `exporter_provenance_verify_failures_total`. +- Logs: `phase=sign`, `error_code`, `signing_key_id`, `cosign_certificate_sn`. +- Alerts: DevOps dashboards (task `DEVOPS-EXPORT-37-001`) trigger on consecutive signing failures or verification failures >0. + +When verification fails downstream, operators should: +1. Confirm signatures using the known-good key. +2. Inspect `provenance.json` materials; rerun the source queries to ensure matching digests. +3. Review run audit logs and retry export with `--resume` to regenerate manifests. + +--- + +## 8. Compliance checklist + +- [ ] Manifests and provenance documents generated with canonical JSON, deterministic digests, and signatures. +- [ ] Cosign public keys published per tenant, rotated through Authority, and distributed to Offline Kit consumers. +- [ ] SLSA attestations enabled where supply-chain requirements demand Level 3 evidence. +- [ ] CLI/Console verification paths documented and tested (CI pipelines exercise `stella export verify`). +- [ ] Encryption metadata (recipients, wrapped keys) recorded in provenance and validated during verification. +- [ ] Run audit logs capture signature timestamps, signer identity, and failure reasons. + +--- + +> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/export-center/trivy-adapter.md b/docs/modules/export-center/trivy-adapter.md similarity index 100% rename from docs/export-center/trivy-adapter.md rename to docs/modules/export-center/trivy-adapter.md diff --git a/docs/modules/graph/AGENTS.md b/docs/modules/graph/AGENTS.md new file mode 100644 index 00000000..f3e00b60 --- /dev/null +++ b/docs/modules/graph/AGENTS.md @@ -0,0 +1,22 @@ +# Graph agent guide + +## Mission +Graph module (upcoming) will power graph-indexed queries for SBOM relationships, lineage, and blast-radius analysis. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/graph/README.md b/docs/modules/graph/README.md new file mode 100644 index 00000000..8a6057df --- /dev/null +++ b/docs/modules/graph/README.md @@ -0,0 +1,31 @@ +# StellaOps Graph + +Graph module (upcoming) will power graph-indexed queries for SBOM relationships, lineage, and blast-radius analysis. + +## Responsibilities +- Model SBOM and advisory entities as a navigable graph. +- Provide APIs for dependency impact, provenance chains, and reachability analysis. +- Integrate with Scheduler/Policy for graph-driven re-evaluation. +- Expose tooling for offline explorers. + +### Domain highlights (Epic 5) +- **Nodes:** artifacts/images, SBOM components, packages/versions, files/paths, licences, advisories, VEX statements, provenance attestations, policy versions. +- **Edges:** `depends_on`, `contains`, `built_from`, `declared_in`, `affected_by`, `vex_exempts`, `governs_with`, `produced_by`, each timestamped and tenant-scoped. +- **Overlays:** policy verdict overlays, VEX consensus, runtime telemetry, and export-ready snapshots with diff support. +- **Queries:** reachability (`impact(graph, advisory)`), blast radius (`reverseDepends(component)`), provenance timeline, saved query library with semantic zoom for Console. + +## Key components +- Planned services documented in implementation plan (to be delivered). + +## Integrations & dependencies +- SBOM Service / Cartographer for data ingestion. +- Policy & CLI for query surfaces. + +## Operational notes +- Pending — see implementation plan for staged milestones. + +## Backlog references +- DOCS-GRAPH-24-003 (architecture index) and SCHED-MODELS-21-001 tasks. + +## Epic alignment +- **Epic 5 – SBOM Graph Explorer:** deliver graph indexer, API, Console explorer, saved queries, overlays, and exports. diff --git a/docs/modules/graph/TASKS.md b/docs/modules/graph/TASKS.md new file mode 100644 index 00000000..1fa607db --- /dev/null +++ b/docs/modules/graph/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Graph + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| GRAPH-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| GRAPH-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| GRAPH-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/modules/graph/architecture.md b/docs/modules/graph/architecture.md new file mode 100644 index 00000000..ec6b936a --- /dev/null +++ b/docs/modules/graph/architecture.md @@ -0,0 +1,56 @@ +# Graph architecture + +> Derived from Epic 5 – SBOM Graph Explorer; this section captures the core model, pipeline, and API expectations. Extend with diagrams as implementation matures. + +## 1) Core model + +- **Nodes:** + - `Artifact` (application/image digest) with metadata (tenant, environment, labels). + - `Component` (package/version, purl, ecosystem). + - `File`/`Path` (source files, binary paths) with hash/time metadata. + - `License` nodes linked to components and SBOM attestations. + - `Advisory` and `VEXStatement` nodes linking to Concelier/Excititor records via digests. + - `PolicyVersion` nodes representing signed policy packs. +- **Edges:** directed, timestamped relationships such as `DEPENDS_ON`, `BUILT_FROM`, `DECLARED_IN`, `AFFECTED_BY`, `VEX_EXEMPTS`, `GOVERNS_WITH`, `OBSERVED_RUNTIME`. Each edge carries provenance (SRM hash, SBOM digest, policy run ID). +- **Overlays:** computed index tables providing fast access to reachability, blast radius, and differential views (e.g., `graph_overlay/vuln/{tenant}/{advisoryKey}`). + +## 2) Pipelines + +1. **Ingestion:** Cartographer/SBOM Service emit SBOM snapshots (`sbom_snapshot` events) captured by the Graph Indexer. Advisories/VEX from Concelier/Excititor generate edge updates, policy runs attach overlay metadata. +2. **ETL:** Normalises nodes/edges into canonical IDs, deduplicates, enforces tenant partitions, and writes to the graph store (planned: Neo4j-compatible or document + adjacency lists in Mongo). +3. **Overlay computation:** Batch workers build materialised views for frequently used queries (impact lists, saved queries, policy overlays) and store as immutable blobs for Offline Kit exports. +4. **Diffing:** `graph_diff` jobs compare two snapshots (e.g., pre/post deploy) and generate signed diff manifests for UI/CLI consumption. + +## 3) APIs + +- `GET /graph/nodes/{id}` — fetch node with metadata and attached provenance. +- `POST /graph/query/saved` — execute saved query (Cypher-like DSL) with tenant filtering; supports paging, citation metadata, and `explain` traces. +- `GET /graph/impact/{advisoryKey}` — returns impacted artifacts with path context and policy/vex overlays. +- `GET /graph/diff/{snapshotA}/{snapshotB}` — streaming API returning diff manifest including new/removed edges, risk summary, and export references. +- `POST /graph/overlay/policy` — create or retrieve overlay for policy version + advisory set, referencing `effective_finding` results. + +## 4) Storage considerations + +- Backed by either: + - **Document + adjacency** (Mongo collections `graph_nodes`, `graph_edges`, `graph_overlays`) with deterministic ordering and streaming exports. + - Or **Graph DB** (e.g., Neo4j/Cosmos Gremlin) behind an abstraction layer; choice depends on deployment footprint. +- All storages require tenant partitioning, append-only change logs, and export manifests for Offline Kits. + +## 5) Offline & export + +- Each snapshot packages `nodes.jsonl`, `edges.jsonl`, `overlays/` plus manifest with hash, counts, and provenance. Export Center consumes these artefacts for graph-specific bundles. +- Saved queries and overlays include deterministic IDs so Offline Kit consumers can import and replay results. + +## 6) Observability + +- Metrics: ingestion lag (`graph_ingest_lag_seconds`), node/edge counts, query latency per saved query, overlay generation duration. +- Logs: structured events for ETL stages and query execution (with trace IDs). +- Traces: ETL pipeline spans, query engine spans. + +## 7) Rollout notes + +- Phase 1: ingest SBOM + advisories, deliver impact queries. +- Phase 2: add VEX overlays, policy overlays, diff tooling. +- Phase 3: expose runtime/Zastava edges and AI-assisted recommendations (future). + +Refer to the module README and implementation plan for immediate context, and update this document once component boundaries and data flows are finalised. diff --git a/docs/modules/graph/implementation_plan.md b/docs/modules/graph/implementation_plan.md new file mode 100644 index 00000000..7a090ded --- /dev/null +++ b/docs/modules/graph/implementation_plan.md @@ -0,0 +1,64 @@ +# Implementation plan — Graph + +## Delivery phases +- **Phase 1 – Graph Indexer foundations** + Stand up Graph Indexer service, node/edge schemas, ingestion from SBOM/Concelier/Excititor events, identity stability, and snapshot materialisation. +- **Phase 2 – Graph API service** + Expose search, query, path, impact, diff, and overlay endpoints with RBAC, cost controls, and streaming responses. +- **Phase 3 – Console & CLI experiences** + Ship Graph Explorer UI (WebGL canvas, filters, diff mode, overlays) and CLI (`stella sbom graph ...`) for automation pipelines. +- **Phase 4 – Advanced analytics** + Implement clustering, centrality, saved queries, overlay caching, and Policy Engine explain integration. +- **Phase 5 – Exports & offline** + Deliver GraphML/CSV/NDJSON exports, Offline Kit bundles (`nodes.jsonl`, `edges.jsonl`, overlays), and deterministic manifests. +- **Phase 6 – Observability & hardening** + Complete dashboards, alerts, runbooks, load/perf testing, and a11y/accessibility review. + +## Work breakdown +- **Services** + - Graph Indexer: event consumers, node/edge builders, snapshot/version handling, aggregate metrics. + - Graph API: validation, planner/cost guard, streaming tile engine, diff/overlay builder, exports. + - Worker jobs: clustering, diff, overlay materialisation with backpressure awareness. +- **Data model & storage** + - Collections/tables (`graph_nodes`, `graph_edges`, `graph_snapshots`, `graph_saved_queries`, `graph_overlays_cache`), indexes, tenant partitioning, append-only change logs. + - Evaluate document + adjacency vs graph DB abstraction; ensure deterministic serialization for exports. +- **Console** + - Feature module `graph-explorer` with routes, canvas renderer, panels, diff UI, saved queries, export workflows, a11y pass. + - Telemetry instrumentation for user interactions and query budgets. +- **CLI & SDK** + - `stella sbom graph query|diff|impact|export`, with JSON schema and piping support. + - SDK utilities for automation and CI pipelines. +- **Policy & VEX integration** + - Fetch explain traces for policy overlays, integrate VEX suppressions, align with Policy Engine & VEX Lens data models. +- **Observability & Ops** + - Metrics (ingest lag, query latency, cache hit rate), log/traces, dashboards, alerting for runaway queries and OOM. + - Runbooks for incident classes (query denial, cache poisoning, degraded render). +- **Documentation** + - Maintain overview, API, query language, console guide, CLI reference, policy/VEX integration docs with compliance checklists. + +## Acceptance criteria +- Graph Indexer ingests SBOM/advisory/VEX events deterministically with tenant isolation and append-only provenance. +- Graph API serves search/query/path/diff/overlay endpoints within budgeted latency and enforces cost limits + RBAC. +- Console explorer visualises topology, overlays, diffs, saved queries; CLI commands mirror functionality for automation. +- Exports (GraphML/CSV/NDJSON) and Offline Kit bundles reproduce snapshots and overlays with signed manifests. +- Observability dashboards/alerts detect ingest lag, query failures, cache churn, and memory pressure; runbooks guide remediation. +- Policy/VEX overlays align with Policy Engine explain traces and VEX suppressions. + +## Risks & mitigations +- **Graph scale/complexity:** adopt adjacency compression, cached overlays, streaming pagination, enforced query budgets. +- **Tenant bleed:** strict tenant filters, fuzz tests, data masking, compliance reviews. +- **Runaway queries/visualization:** cost planner, query timeout, UI hints, safe mode renders. +- **Cache poisoning:** input validation, schema versioning, eviction policies. +- **Offline parity gaps:** deterministic export pipeline, integration tests for Offline Kit import. + +## Test strategy +- **Unit:** node/edge builders, identifier stability, overlay computations, query planner, diff engine. +- **Integration:** end-to-end ingest + query flows across SBOM/advisory/VEX, saved query execution, diff exports. +- **Performance:** large SBOM datasets, concurrency, memory profiling, WebGL rendering. +- **Security:** tenant isolation tests, RBAC, query cost abuse. +- **Offline:** export/import verification, manifest hashing, CLI replay. + +## Definition of done +- All phases delivered with telemetry, documentation, runbooks, and Offline Kit parity. +- Console/CLI parity validated; a11y review complete. +- ./TASKS.md and ../../TASKS.md updated; README/architecture/plan kept current with imposed rule references. diff --git a/docs/modules/notify/AGENTS.md b/docs/modules/notify/AGENTS.md new file mode 100644 index 00000000..373bd0a2 --- /dev/null +++ b/docs/modules/notify/AGENTS.md @@ -0,0 +1,22 @@ +# Notify agent guide + +## Mission +Notify evaluates operator-defined rules against platform events and dispatches channel-specific payloads with full auditability. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/notify/README.md b/docs/modules/notify/README.md new file mode 100644 index 00000000..ae9c07d6 --- /dev/null +++ b/docs/modules/notify/README.md @@ -0,0 +1,35 @@ +# StellaOps Notify + +Notify evaluates operator-defined rules against platform events and dispatches channel-specific payloads with full auditability. + +## Responsibilities +- Process event streams and apply tenant-scoped routing rules. +- Render connector-specific payloads (email, Slack, Teams, webhook, custom). +- Enforce throttling, digests, and delivery retries. +- Surface delivery/audit data for UI and CLI consumers. + +## Key components +- `StellaOps.Notify.WebService` (rules API + preview). +- `StellaOps.Notify.Worker` (delivery engine). +- Connector libraries under `StellaOps.Notify.Connectors.*`. + +## Integrations & dependencies +- MongoDB for rule/channel storage. +- Redis/NATS for delivery queues. +- CLI/UI for authoring and monitoring notifications. + +## Operational notes +- Schema fixtures in ./resources/schemas & ./resources/samples. +- Connector-specific monitoring dashboards. +- Offline runner guidance inside operations playbook. + +## Related resources +- ./resources/schemas +- ./resources/samples + +## Backlog references +- NOTIFY-SVC-38..40 (Notify backlog) referenced in `docs/README.md`. +- DOCS-NOTIFY updates tracked in ../../TASKS.md when available. + +## Epic alignment +- **Epic 11 – Notifications Studio:** deliver notifications workspace, preview tooling, immutable delivery ledger, and tenant-scoped throttling/digest controls. diff --git a/docs/modules/notify/TASKS.md b/docs/modules/notify/TASKS.md new file mode 100644 index 00000000..371b0758 --- /dev/null +++ b/docs/modules/notify/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Notify + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| NOTIFY-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| NOTIFY-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| NOTIFY-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_NOTIFY.md b/docs/modules/notify/architecture.md similarity index 94% rename from docs/ARCHITECTURE_NOTIFY.md rename to docs/modules/notify/architecture.md index b953de2f..4bf3d27a 100644 --- a/docs/ARCHITECTURE_NOTIFY.md +++ b/docs/modules/notify/architecture.md @@ -1,515 +1,515 @@ -> **Scope.** Implementation‑ready architecture for **Notify**: a rules‑driven, tenant‑aware notification service that consumes platform events (scan completed, report ready, rescan deltas, attestation logged, admission decisions, etc.), evaluates operator‑defined routing rules, renders **channel‑specific messages** (Slack/Teams/Email/Webhook), and delivers them **reliably** with idempotency, throttling, and digests. It is UI‑managed, auditable, and safe by default (no secrets leakage, no spam storms). - ---- - -## 0) Mission & boundaries - -**Mission.** Convert **facts** from Stella Ops into **actionable, noise‑controlled** signals where teams already live (chat/email/webhooks), with **explainable** reasons and deep links to the UI. - -**Boundaries.** - -* Notify **does not make policy decisions** and **does not rescan**; it **consumes** events from Scanner/Scheduler/Vexer/Feedser/Attestor/Zastava and routes them. -* Attachments are **links** (UI/attestation pages); Notify **does not** attach SBOMs or large blobs to messages. -* Secrets for channels (Slack tokens, SMTP creds) are **referenced**, not stored raw in Mongo. - ---- - -## 1) Runtime shape & projects - -``` -src/ - ├─ StellaOps.Notify.WebService/ # REST: rules/channels CRUD, test send, deliveries browse - ├─ StellaOps.Notify.Worker/ # consumers + evaluators + renderers + delivery workers - ├─ StellaOps.Notify.Connectors.* / # channel plug-ins: Slack, Teams, Email, Webhook (v1) - │ └─ *.Tests/ - ├─ StellaOps.Notify.Engine/ # rules engine, templates, idempotency, digests, throttles - ├─ StellaOps.Notify.Models/ # DTOs (Rule, Channel, Event, Delivery, Template) - ├─ StellaOps.Notify.Storage.Mongo/ # rules, channels, deliveries, digests, locks - ├─ StellaOps.Notify.Queue/ # bus client (Redis Streams/NATS JetStream) - └─ StellaOps.Notify.Tests.* # unit/integration/e2e -``` - -**Deployables**: - -* **Notify.WebService** (stateless API) -* **Notify.Worker** (horizontal scale) - -**Dependencies**: Authority (OpToks; DPoP/mTLS), MongoDB, Redis/NATS (bus), HTTP egress to Slack/Teams/Webhooks, SMTP relay for Email. - -> **Configuration.** Notify.WebService bootstraps from `notify.yaml` (see `etc/notify.yaml.sample`). Use `storage.driver: mongo` with a production connection string; the optional `memory` driver exists only for tests. Authority settings follow the platform defaults—when running locally without Authority, set `authority.enabled: false` and supply `developmentSigningKey` so JWTs can be validated offline. -> -> `api.rateLimits` exposes token-bucket controls for delivery history queries and test-send previews (`deliveryHistory`, `testSend`). Default values allow generous browsing while preventing accidental bursts; operators can relax/tighten the buckets per deployment. - -> **Plug-ins.** All channel connectors are packaged under `/plugins/notify`. The ordered load list must start with Slack/Teams before Email/Webhook so chat-first actions are registered deterministically for Offline Kit bundles: -> -> ```yaml -> plugins: -> baseDirectory: "/var/opt/stellaops" -> directory: "plugins/notify" -> orderedPlugins: -> - StellaOps.Notify.Connectors.Slack -> - StellaOps.Notify.Connectors.Teams -> - StellaOps.Notify.Connectors.Email -> - StellaOps.Notify.Connectors.Webhook -> ``` -> -> The Offline Kit job simply copies the `plugins/notify` tree into the air-gapped bundle; the ordered list keeps connector manifests stable across environments. - -> **Authority clients.** Register two OAuth clients in StellaOps Authority: `notify-web-dev` (audience `notify.dev`) for development and `notify-web` (audience `notify`) for staging/production. Both require `notify.read` and `notify.admin` scopes and use DPoP-bound client credentials (`client_secret` in the samples). Reference entries live in `etc/authority.yaml.sample`, with placeholder secrets under `etc/secrets/notify-web*.secret.example`. - ---- - -## 2) Responsibilities - -1. **Ingest** platform events from internal bus with strong ordering per key (e.g., image digest). -2. **Evaluate rules** (tenant‑scoped) with matchers: severity changes, namespaces, repos, labels, KEV flags, provider provenance (VEX), component keys, admission decisions, etc. -3. **Control noise**: **throttle**, **coalesce** (digest windows), and **dedupe** via idempotency keys. -4. **Render** channel‑specific messages using safe templates; include **evidence** and **links**. -5. **Deliver** with retries/backoff; record outcome; expose delivery history to UI. -6. **Test** paths (send test to channel targets) without touching live rules. -7. **Audit**: log who configured what, when, and why a message was sent. - ---- - -## 3) Event model (inputs) - -Notify subscribes to the **internal event bus** (produced by services, escaped JSON; gzip allowed with caps): - -* `scanner.scan.completed` — new SBOM(s) composed; artifacts ready -* `scanner.report.ready` — analysis verdict (policy+vex) available; carries deltas summary -* `scheduler.rescan.delta` — new findings after Feedser/Vexer deltas (already summarized) -* `attestor.logged` — Rekor UUID returned (sbom/report/vex export) -* `zastava.admission` — admit/deny with reasons, namespace, image digests -* `feedser.export.completed` — new export ready (rarely notified directly; usually drives Scheduler) -* `vexer.export.completed` — new consensus snapshot (ditto) - -**Canonical envelope (bus → Notify.Engine):** - -```json -{ - "eventId": "uuid", - "kind": "scanner.report.ready", - "tenant": "tenant-01", - "ts": "2025-10-18T05:41:22Z", - "actor": "scanner-webservice", - "scope": { "namespace":"payments", "repo":"ghcr.io/acme/api", "digest":"sha256:..." }, - "payload": { /* kind-specific fields, see below */ } -} -``` - -**Examples (payload cores):** - -* `scanner.report.ready`: - - ```json - { - "reportId": "report-3def...", - "verdict": "fail", - "summary": {"total": 12, "blocked": 2, "warned": 3, "ignored": 5, "quieted": 2}, - "delta": {"newCritical": 1, "kev": ["CVE-2025-..."]}, - "links": {"ui": "https://ui/.../reports/report-3def...", "rekor": "https://rekor/..."}, - "dsse": { "...": "..." }, - "report": { "...": "..." } - } - ``` - - Payload embeds both the canonical report document and the DSSE envelope so connectors, Notify, and UI tooling can reuse the signed bytes without re-serialising. - -* `scanner.scan.completed`: - - ```json - { - "reportId": "report-3def...", - "digest": "sha256:...", - "verdict": "fail", - "summary": {"total": 12, "blocked": 2, "warned": 3, "ignored": 5, "quieted": 2}, - "delta": {"newCritical": 1, "kev": ["CVE-2025-..."]}, - "policy": {"revisionId": "rev-42", "digest": "27d2..."}, - "findings": [{"id": "finding-1", "severity": "Critical", "cve": "CVE-2025-...", "reachability": "runtime"}], - "dsse": { "...": "..." } - } - ``` - -* `zastava.admission`: - - ```json - { "decision":"deny|allow", "reasons":["unsigned image","missing SBOM"], - "images":[{"digest":"sha256:...","signed":false,"hasSbom":false}] } - ``` - ---- - -## 4) Rules engine — semantics - -**Rule shape (simplified):** - -```yaml -name: "high-critical-alerts-prod" -enabled: true -match: - eventKinds: ["scanner.report.ready","scheduler.rescan.delta","zastava.admission"] - namespaces: ["prod-*"] - repos: ["ghcr.io/acme/*"] - minSeverity: "high" # min of new findings (delta context) - kev: true # require KEV-tagged or allow any if false - verdict: ["fail","deny"] # filter for report/admission - vex: - includeRejectedJustifications: false # notify only on accepted 'affected' -actions: - - channel: "slack:sec-alerts" # reference to Channel object - template: "concise" - throttle: "5m" - - channel: "email:soc" - digest: "hourly" - template: "detailed" -``` - -**Evaluation order** - -1. **Tenant check** → discard if rule tenant ≠ event tenant. -2. **Kind filter** → discard early. -3. **Scope match** (namespace/repo/labels). -4. **Delta/severity gates** (if event carries `delta`). -5. **VEX gate** (drop if event’s finding is not affected under policy consensus unless rule says otherwise). -6. **Throttling/dedup** (idempotency key) — skip if suppressed. -7. **Actions** → enqueue per‑channel job(s). - -**Idempotency key**: `hash(ruleId | actionId | event.kind | scope.digest | delta.hash | day-bucket)`; ensures “same alert” doesn’t fire more than once within throttle window. - -**Digest windows**: maintain per action a **coalescer**: - -* Window: `5m|15m|1h|1d` (configurable); coalesces events by tenant + namespace/repo or by digest group. -* Digest messages summarize top N items and counts, with safe truncation. - ---- - -## 5) Channels & connectors (plug‑ins) - -Channel config is **two‑part**: a **Channel** record (name, type, options) and a Secret **reference** (Vault/K8s Secret). Connectors are **restart-time plug-ins** discovered on service start (same manifest convention as Concelier/Excititor) and live under `plugins/notify//`. - -**Built‑in v1:** - -* **Slack**: Bot token (xoxb‑…), `chat.postMessage` + `blocks`; rate limit aware (HTTP 429). -* **Microsoft Teams**: Incoming Webhook (or Graph card later); adaptive card payloads. -* **Email (SMTP)**: TLS (STARTTLS or implicit), From/To/CC/BCC; HTML+text alt; DKIM optional. -* **Generic Webhook**: POST JSON with HMAC signature (Ed25519 or SHA‑256) in headers. - -**Connector contract:** (implemented by plug-in assemblies) - -```csharp -public interface INotifyConnector { - string Type { get; } // "slack" | "teams" | "email" | "webhook" | ... - Task SendAsync(DeliveryContext ctx, CancellationToken ct); - Task HealthAsync(ChannelConfig cfg, CancellationToken ct); -} -``` - -**DeliveryContext** includes **rendered content** and **raw event** for audit. - -**Test-send previews.** Plug-ins can optionally implement `INotifyChannelTestProvider` to shape `/channels/{id}/test` responses. Providers receive a sanitised `ChannelTestPreviewContext` (channel, tenant, target, timestamp, trace) and return a `NotifyDeliveryRendered` preview + metadata. When no provider is present, the host falls back to a generic preview so the endpoint always responds. - -**Secrets**: `ChannelConfig.secretRef` points to Authority‑managed secret handle or K8s Secret path; workers load at send-time; plug-in manifests (`notify-plugin.json`) declare capabilities and version. - ---- - -## 6) Templates & rendering - -**Template engine**: strongly typed, safe Handlebars‑style; no arbitrary code. Partial templates per channel. Deterministic outputs (prop order, no locale drift unless requested). - -**Variables** (examples): - -* `event.kind`, `event.ts`, `scope.namespace`, `scope.repo`, `scope.digest` -* `payload.verdict`, `payload.delta.newCritical`, `payload.links.ui`, `payload.links.rekor` -* `topFindings[]` with `purl`, `vulnId`, `severity` -* `policy.name`, `policy.revision` (if available) - -**Helpers**: - -* `severity_icon(sev)`, `link(text,url)`, `pluralize(n, "finding")`, `truncate(text, n)`, `code(text)`. - -**Channel mapping**: - -* Slack: title + blocks, limited to 50 blocks/3000 chars per section; long lists → link to UI. +> **Scope.** Implementation‑ready architecture for **Notify** (aligned with Epic 11 – Notifications Studio): a rules‑driven, tenant‑aware notification service that consumes platform events (scan completed, report ready, rescan deltas, attestation logged, admission decisions, etc.), evaluates operator‑defined routing rules, renders **channel‑specific messages** (Slack/Teams/Email/Webhook), and delivers them **reliably** with idempotency, throttling, and digests. It is UI‑managed, auditable, and safe by default (no secrets leakage, no spam storms). + +--- + +## 0) Mission & boundaries + +**Mission.** Convert **facts** from Stella Ops into **actionable, noise‑controlled** signals where teams already live (chat/email/webhooks), with **explainable** reasons and deep links to the UI. + +**Boundaries.** + +* Notify **does not make policy decisions** and **does not rescan**; it **consumes** events from Scanner/Scheduler/Vexer/Feedser/Attestor/Zastava and routes them. +* Attachments are **links** (UI/attestation pages); Notify **does not** attach SBOMs or large blobs to messages. +* Secrets for channels (Slack tokens, SMTP creds) are **referenced**, not stored raw in Mongo. + +--- + +## 1) Runtime shape & projects + +``` +src/ + ├─ StellaOps.Notify.WebService/ # REST: rules/channels CRUD, test send, deliveries browse + ├─ StellaOps.Notify.Worker/ # consumers + evaluators + renderers + delivery workers + ├─ StellaOps.Notify.Connectors.* / # channel plug-ins: Slack, Teams, Email, Webhook (v1) + │ └─ *.Tests/ + ├─ StellaOps.Notify.Engine/ # rules engine, templates, idempotency, digests, throttles + ├─ StellaOps.Notify.Models/ # DTOs (Rule, Channel, Event, Delivery, Template) + ├─ StellaOps.Notify.Storage.Mongo/ # rules, channels, deliveries, digests, locks + ├─ StellaOps.Notify.Queue/ # bus client (Redis Streams/NATS JetStream) + └─ StellaOps.Notify.Tests.* # unit/integration/e2e +``` + +**Deployables**: + +* **Notify.WebService** (stateless API) +* **Notify.Worker** (horizontal scale) + +**Dependencies**: Authority (OpToks; DPoP/mTLS), MongoDB, Redis/NATS (bus), HTTP egress to Slack/Teams/Webhooks, SMTP relay for Email. + +> **Configuration.** Notify.WebService bootstraps from `notify.yaml` (see `etc/notify.yaml.sample`). Use `storage.driver: mongo` with a production connection string; the optional `memory` driver exists only for tests. Authority settings follow the platform defaults—when running locally without Authority, set `authority.enabled: false` and supply `developmentSigningKey` so JWTs can be validated offline. +> +> `api.rateLimits` exposes token-bucket controls for delivery history queries and test-send previews (`deliveryHistory`, `testSend`). Default values allow generous browsing while preventing accidental bursts; operators can relax/tighten the buckets per deployment. + +> **Plug-ins.** All channel connectors are packaged under `/plugins/notify`. The ordered load list must start with Slack/Teams before Email/Webhook so chat-first actions are registered deterministically for Offline Kit bundles: +> +> ```yaml +> plugins: +> baseDirectory: "/var/opt/stellaops" +> directory: "plugins/notify" +> orderedPlugins: +> - StellaOps.Notify.Connectors.Slack +> - StellaOps.Notify.Connectors.Teams +> - StellaOps.Notify.Connectors.Email +> - StellaOps.Notify.Connectors.Webhook +> ``` +> +> The Offline Kit job simply copies the `plugins/notify` tree into the air-gapped bundle; the ordered list keeps connector manifests stable across environments. + +> **Authority clients.** Register two OAuth clients in StellaOps Authority: `notify-web-dev` (audience `notify.dev`) for development and `notify-web` (audience `notify`) for staging/production. Both require `notify.read` and `notify.admin` scopes and use DPoP-bound client credentials (`client_secret` in the samples). Reference entries live in `etc/authority.yaml.sample`, with placeholder secrets under `etc/secrets/notify-web*.secret.example`. + +--- + +## 2) Responsibilities + +1. **Ingest** platform events from internal bus with strong ordering per key (e.g., image digest). +2. **Evaluate rules** (tenant‑scoped) with matchers: severity changes, namespaces, repos, labels, KEV flags, provider provenance (VEX), component keys, admission decisions, etc. +3. **Control noise**: **throttle**, **coalesce** (digest windows), and **dedupe** via idempotency keys. +4. **Render** channel‑specific messages using safe templates; include **evidence** and **links**. +5. **Deliver** with retries/backoff; record outcome; expose delivery history to UI. +6. **Test** paths (send test to channel targets) without touching live rules. +7. **Audit**: log who configured what, when, and why a message was sent. + +--- + +## 3) Event model (inputs) + +Notify subscribes to the **internal event bus** (produced by services, escaped JSON; gzip allowed with caps): + +* `scanner.scan.completed` — new SBOM(s) composed; artifacts ready +* `scanner.report.ready` — analysis verdict (policy+vex) available; carries deltas summary +* `scheduler.rescan.delta` — new findings after Feedser/Vexer deltas (already summarized) +* `attestor.logged` — Rekor UUID returned (sbom/report/vex export) +* `zastava.admission` — admit/deny with reasons, namespace, image digests +* `feedser.export.completed` — new export ready (rarely notified directly; usually drives Scheduler) +* `vexer.export.completed` — new consensus snapshot (ditto) + +**Canonical envelope (bus → Notify.Engine):** + +```json +{ + "eventId": "uuid", + "kind": "scanner.report.ready", + "tenant": "tenant-01", + "ts": "2025-10-18T05:41:22Z", + "actor": "scanner-webservice", + "scope": { "namespace":"payments", "repo":"ghcr.io/acme/api", "digest":"sha256:..." }, + "payload": { /* kind-specific fields, see below */ } +} +``` + +**Examples (payload cores):** + +* `scanner.report.ready`: + + ```json + { + "reportId": "report-3def...", + "verdict": "fail", + "summary": {"total": 12, "blocked": 2, "warned": 3, "ignored": 5, "quieted": 2}, + "delta": {"newCritical": 1, "kev": ["CVE-2025-..."]}, + "links": {"ui": "https://ui/.../reports/report-3def...", "rekor": "https://rekor/..."}, + "dsse": { "...": "..." }, + "report": { "...": "..." } + } + ``` + + Payload embeds both the canonical report document and the DSSE envelope so connectors, Notify, and UI tooling can reuse the signed bytes without re-serialising. + +* `scanner.scan.completed`: + + ```json + { + "reportId": "report-3def...", + "digest": "sha256:...", + "verdict": "fail", + "summary": {"total": 12, "blocked": 2, "warned": 3, "ignored": 5, "quieted": 2}, + "delta": {"newCritical": 1, "kev": ["CVE-2025-..."]}, + "policy": {"revisionId": "rev-42", "digest": "27d2..."}, + "findings": [{"id": "finding-1", "severity": "Critical", "cve": "CVE-2025-...", "reachability": "runtime"}], + "dsse": { "...": "..." } + } + ``` + +* `zastava.admission`: + + ```json + { "decision":"deny|allow", "reasons":["unsigned image","missing SBOM"], + "images":[{"digest":"sha256:...","signed":false,"hasSbom":false}] } + ``` + +--- + +## 4) Rules engine — semantics + +**Rule shape (simplified):** + +```yaml +name: "high-critical-alerts-prod" +enabled: true +match: + eventKinds: ["scanner.report.ready","scheduler.rescan.delta","zastava.admission"] + namespaces: ["prod-*"] + repos: ["ghcr.io/acme/*"] + minSeverity: "high" # min of new findings (delta context) + kev: true # require KEV-tagged or allow any if false + verdict: ["fail","deny"] # filter for report/admission + vex: + includeRejectedJustifications: false # notify only on accepted 'affected' +actions: + - channel: "slack:sec-alerts" # reference to Channel object + template: "concise" + throttle: "5m" + - channel: "email:soc" + digest: "hourly" + template: "detailed" +``` + +**Evaluation order** + +1. **Tenant check** → discard if rule tenant ≠ event tenant. +2. **Kind filter** → discard early. +3. **Scope match** (namespace/repo/labels). +4. **Delta/severity gates** (if event carries `delta`). +5. **VEX gate** (drop if event’s finding is not affected under policy consensus unless rule says otherwise). +6. **Throttling/dedup** (idempotency key) — skip if suppressed. +7. **Actions** → enqueue per‑channel job(s). + +**Idempotency key**: `hash(ruleId | actionId | event.kind | scope.digest | delta.hash | day-bucket)`; ensures “same alert” doesn’t fire more than once within throttle window. + +**Digest windows**: maintain per action a **coalescer**: + +* Window: `5m|15m|1h|1d` (configurable); coalesces events by tenant + namespace/repo or by digest group. +* Digest messages summarize top N items and counts, with safe truncation. + +--- + +## 5) Channels & connectors (plug‑ins) + +Channel config is **two‑part**: a **Channel** record (name, type, options) and a Secret **reference** (Vault/K8s Secret). Connectors are **restart-time plug-ins** discovered on service start (same manifest convention as Concelier/Excititor) and live under `plugins/notify//`. + +**Built‑in v1:** + +* **Slack**: Bot token (xoxb‑…), `chat.postMessage` + `blocks`; rate limit aware (HTTP 429). +* **Microsoft Teams**: Incoming Webhook (or Graph card later); adaptive card payloads. +* **Email (SMTP)**: TLS (STARTTLS or implicit), From/To/CC/BCC; HTML+text alt; DKIM optional. +* **Generic Webhook**: POST JSON with HMAC signature (Ed25519 or SHA‑256) in headers. + +**Connector contract:** (implemented by plug-in assemblies) + +```csharp +public interface INotifyConnector { + string Type { get; } // "slack" | "teams" | "email" | "webhook" | ... + Task SendAsync(DeliveryContext ctx, CancellationToken ct); + Task HealthAsync(ChannelConfig cfg, CancellationToken ct); +} +``` + +**DeliveryContext** includes **rendered content** and **raw event** for audit. + +**Test-send previews.** Plug-ins can optionally implement `INotifyChannelTestProvider` to shape `/channels/{id}/test` responses. Providers receive a sanitised `ChannelTestPreviewContext` (channel, tenant, target, timestamp, trace) and return a `NotifyDeliveryRendered` preview + metadata. When no provider is present, the host falls back to a generic preview so the endpoint always responds. + +**Secrets**: `ChannelConfig.secretRef` points to Authority‑managed secret handle or K8s Secret path; workers load at send-time; plug-in manifests (`notify-plugin.json`) declare capabilities and version. + +--- + +## 6) Templates & rendering + +**Template engine**: strongly typed, safe Handlebars‑style; no arbitrary code. Partial templates per channel. Deterministic outputs (prop order, no locale drift unless requested). + +**Variables** (examples): + +* `event.kind`, `event.ts`, `scope.namespace`, `scope.repo`, `scope.digest` +* `payload.verdict`, `payload.delta.newCritical`, `payload.links.ui`, `payload.links.rekor` +* `topFindings[]` with `purl`, `vulnId`, `severity` +* `policy.name`, `policy.revision` (if available) + +**Helpers**: + +* `severity_icon(sev)`, `link(text,url)`, `pluralize(n, "finding")`, `truncate(text, n)`, `code(text)`. + +**Channel mapping**: + +* Slack: title + blocks, limited to 50 blocks/3000 chars per section; long lists → link to UI. * Teams: Adaptive Card schema 1.5; fallback text for older channels (surfaced as `teams.fallbackText` metadata alongside webhook hash). -* Email: HTML + text; inline table of top N findings, rest behind UI link. -* Webhook: JSON with `event`, `ruleId`, `actionId`, `summary`, `links`, and raw `payload` subset. - -**i18n**: template set per locale (English default; Bulgarian built‑in). - ---- - -## 7) Data model (Mongo) - -Canonical JSON Schemas for rules/channels/events live in `docs/notify/schemas/`. Sample payloads intended for tests/UI mock responses are captured in `docs/notify/samples/`. - -**Database**: `notify` - -* `rules` - - ``` - { _id, tenantId, name, enabled, match, actions, createdBy, updatedBy, createdAt, updatedAt } - ``` - -* `channels` - - ``` - { _id, tenantId, name:"slack:sec-alerts", type:"slack", - config:{ webhookUrl?:"", channel:"#sec-alerts", workspace?: "...", secretRef:"ref://..." }, - createdAt, updatedAt } - ``` - -* `deliveries` - - ``` - { _id, tenantId, ruleId, actionId, eventId, kind, scope, status:"sent|failed|throttled|digested|dropped", - attempts:[{ts, status, code, reason}], - rendered:{ title, body, target }, // redacted for PII; body hash stored - sentAt, lastError? } - ``` - -* `digests` - - ``` - { _id, tenantId, actionKey, window:"hourly", openedAt, items:[{eventId, scope, delta}], status:"open|flushed" } - ``` - -* `throttles` - - ``` - { key:"idem:", ttlAt } // short-lived, also cached in Redis - ``` - -**Indexes**: rules by `{tenantId, enabled}`, deliveries by `{tenantId, sentAt desc}`, digests by `{tenantId, actionKey}`. - ---- - -## 8) External APIs (WebService) - -Base path: `/api/v1/notify` (Authority OpToks; scopes: `notify.admin` for write, `notify.read` for view). - -*All* REST calls require the tenant header `X-StellaOps-Tenant` (matches the canonical `tenantId` stored in Mongo). Payloads are normalised via `NotifySchemaMigration` before persistence to guarantee schema version pinning. - -Authentication today is stubbed with Bearer tokens (`Authorization: Bearer `). When Authority wiring lands, this will switch to OpTok validation + scope enforcement, but the header contract will remain the same. - -Service configuration exposes `notify:auth:*` keys (issuer, audience, signing key, scope names) so operators can wire the Authority JWKS or (in dev) a symmetric test key. `notify:storage:*` keys cover Mongo URI/database/collection overrides. Both sets are required for the new API surface. - -Internal tooling can hit `/internal/notify//normalize` to upgrade legacy JSON and return canonical output used in the docs fixtures. - -* **Channels** - - * `POST /channels` | `GET /channels` | `GET /channels/{id}` | `PATCH /channels/{id}` | `DELETE /channels/{id}` - * `POST /channels/{id}/test` → send sample message (no rule evaluation); returns `202 Accepted` with rendered preview + metadata (base keys: `channelType`, `target`, `previewProvider`, `traceId` + connector-specific entries); governed by `api.rateLimits:testSend`. +* Email: HTML + text; inline table of top N findings, rest behind UI link. +* Webhook: JSON with `event`, `ruleId`, `actionId`, `summary`, `links`, and raw `payload` subset. + +**i18n**: template set per locale (English default; Bulgarian built‑in). + +--- + +## 7) Data model (Mongo) + +Canonical JSON Schemas for rules/channels/events live in `docs/modules/notify/resources/schemas/`. Sample payloads intended for tests/UI mock responses are captured in `docs/modules/notify/resources/samples/`. + +**Database**: `notify` + +* `rules` + + ``` + { _id, tenantId, name, enabled, match, actions, createdBy, updatedBy, createdAt, updatedAt } + ``` + +* `channels` + + ``` + { _id, tenantId, name:"slack:sec-alerts", type:"slack", + config:{ webhookUrl?:"", channel:"#sec-alerts", workspace?: "...", secretRef:"ref://..." }, + createdAt, updatedAt } + ``` + +* `deliveries` + + ``` + { _id, tenantId, ruleId, actionId, eventId, kind, scope, status:"sent|failed|throttled|digested|dropped", + attempts:[{ts, status, code, reason}], + rendered:{ title, body, target }, // redacted for PII; body hash stored + sentAt, lastError? } + ``` + +* `digests` + + ``` + { _id, tenantId, actionKey, window:"hourly", openedAt, items:[{eventId, scope, delta}], status:"open|flushed" } + ``` + +* `throttles` + + ``` + { key:"idem:", ttlAt } // short-lived, also cached in Redis + ``` + +**Indexes**: rules by `{tenantId, enabled}`, deliveries by `{tenantId, sentAt desc}`, digests by `{tenantId, actionKey}`. + +--- + +## 8) External APIs (WebService) + +Base path: `/api/v1/notify` (Authority OpToks; scopes: `notify.admin` for write, `notify.read` for view). + +*All* REST calls require the tenant header `X-StellaOps-Tenant` (matches the canonical `tenantId` stored in Mongo). Payloads are normalised via `NotifySchemaMigration` before persistence to guarantee schema version pinning. + +Authentication today is stubbed with Bearer tokens (`Authorization: Bearer `). When Authority wiring lands, this will switch to OpTok validation + scope enforcement, but the header contract will remain the same. + +Service configuration exposes `notify:auth:*` keys (issuer, audience, signing key, scope names) so operators can wire the Authority JWKS or (in dev) a symmetric test key. `notify:storage:*` keys cover Mongo URI/database/collection overrides. Both sets are required for the new API surface. + +Internal tooling can hit `/internal/notify//normalize` to upgrade legacy JSON and return canonical output used in the docs fixtures. + +* **Channels** + + * `POST /channels` | `GET /channels` | `GET /channels/{id}` | `PATCH /channels/{id}` | `DELETE /channels/{id}` + * `POST /channels/{id}/test` → send sample message (no rule evaluation); returns `202 Accepted` with rendered preview + metadata (base keys: `channelType`, `target`, `previewProvider`, `traceId` + connector-specific entries); governed by `api.rateLimits:testSend`. * `GET /channels/{id}/health` → connector self‑check (returns redacted metadata: secret refs hashed, sensitive config keys masked, fallbacks noted via `teams.fallbackText`/`teams.validation.*`) - -* **Rules** - - * `POST /rules` | `GET /rules` | `GET /rules/{id}` | `PATCH /rules/{id}` | `DELETE /rules/{id}` - * `POST /rules/{id}/test` → dry‑run rule against a **sample event** (no delivery unless `--send`) - -* **Deliveries** - - * `POST /deliveries` → ingest worker delivery state (idempotent via `deliveryId`). - * `GET /deliveries?since=...&status=...&limit=...` → list envelope `{ items, count, continuationToken }` (most recent first); base metadata keys match the test-send response (`channelType`, `target`, `previewProvider`, `traceId`); rate-limited via `api.rateLimits.deliveryHistory`. See `docs/notify/samples/notify-delivery-list-response.sample.json`. - * `GET /deliveries/{id}` → detail (redacted body + metadata) - * `POST /deliveries/{id}/retry` → force retry (admin, future sprint) - -* **Admin** - - * `GET /stats` (per tenant counts, last hour/day) - * `GET /healthz|readyz` (liveness) - * `POST /locks/acquire` | `POST /locks/release` – worker coordination primitives (short TTL). - * `POST /digests` | `GET /digests/{actionKey}` | `DELETE /digests/{actionKey}` – manage open digest windows. - * `POST /audit` | `GET /audit?since=&limit=` – append/query structured audit trail entries. - -**Ingestion**: workers do **not** expose public ingestion; they **subscribe** to the internal bus. (Optional `/events/test` for integration testing, admin‑only.) - ---- - -## 9) Delivery pipeline (worker) - -``` -[Event bus] → [Ingestor] → [RuleMatcher] → [Throttle/Dedupe] → [DigestCoalescer] → [Renderer] → [Connector] → [Result] - └────────→ [DeliveryStore] -``` - -* **Ingestor**: N consumers with per‑key ordering (key = tenant|digest|namespace). -* **RuleMatcher**: loads active rules snapshot for tenant into memory; vectorized predicate check. -* **Throttle/Dedupe**: consult Redis + Mongo `throttles`; if hit → record `status=throttled`. -* **DigestCoalescer**: append to open digest window or flush when timer expires. -* **Renderer**: select template (channel+locale), inject variables, enforce length limits, compute `bodyHash`. -* **Connector**: send; handle provider‑specific rate limits and backoffs; `maxAttempts` with exponential jitter; overflow → DLQ (dead‑letter topic) + UI surfacing. - -**Idempotency**: per action **idempotency key** stored in Redis (TTL = `throttle window` or `digest window`). Connectors also respect **provider** idempotency where available (e.g., Slack `client_msg_id`). - ---- - -## 10) Reliability & rate controls - -* **Per‑tenant** RPM caps (default 600/min) + **per‑channel** concurrency (Slack 1–4, Teams 1–2, Email 8–32 based on relay). -* **Backoff** map: Slack 429 → respect `Retry‑After`; SMTP 4xx → retry; 5xx → retry with jitter; permanent rejects → drop with status recorded. -* **DLQ**: NATS/Redis stream `notify.dlq` with `{event, rule, action, error}` for operator inspection; UI shows DLQ items. - ---- - -## 11) Security & privacy - -* **AuthZ**: all APIs require **Authority** OpToks; actions scoped by tenant. -* **Secrets**: `secretRef` only; Notify fetches just‑in‑time from Authority Secret proxy or K8s Secret (mounted). No plaintext secrets in Mongo. -* **Egress TLS**: validate SSL; pin domains per channel config; optional CA bundle override for on‑prem SMTP. -* **Webhook signing**: HMAC or Ed25519 signatures in `X-StellaOps-Signature` + replay‑window timestamp; include canonical body hash in header. -* **Redaction**: deliveries store **hashes** of bodies, not full payloads for chat/email to minimize PII retention (configurable). -* **Quiet hours**: per tenant (e.g., 22:00–06:00) route high‑sev only; defer others to digests. -* **Loop prevention**: Webhook target allowlist + event origin tags; do not ingest own webhooks. - ---- - -## 12) Observability (Prometheus + OTEL) - -* `notify.events_consumed_total{kind}` -* `notify.rules_matched_total{ruleId}` -* `notify.throttled_total{reason}` -* `notify.digest_coalesced_total{window}` -* `notify.sent_total{channel}` / `notify.failed_total{channel,code}` -* `notify.delivery_latency_seconds{channel}` (end‑to‑end) -* **Tracing**: spans `ingest`, `match`, `render`, `send`; correlation id = `eventId`. - -**SLO targets** - -* Event→delivery p95 **≤ 30–60 s** under nominal load. -* Failure rate p95 **< 0.5%** per hour (excluding provider outages). -* Duplicate rate **≈ 0** (idempotency working). - ---- - -## 13) Configuration (YAML) - -```yaml -notify: - authority: - issuer: "https://authority.internal" - require: "dpop" # or "mtls" - bus: - kind: "redis" # or "nats" - streams: - - "scanner.events" - - "scheduler.events" - - "attestor.events" - - "zastava.events" - mongo: - uri: "mongodb://mongo/notify" - limits: - perTenantRpm: 600 - perChannel: - slack: { concurrency: 2 } - teams: { concurrency: 1 } - email: { concurrency: 8 } - webhook: { concurrency: 8 } - digests: - defaultWindow: "1h" - maxItems: 100 - quietHours: - enabled: true - window: "22:00-06:00" - minSeverity: "critical" - webhooks: - sign: - method: "ed25519" # or "hmac-sha256" - keyRef: "ref://notify/webhook-sign-key" -``` - ---- - -## 14) UI touch‑points - -* **Notifications → Channels**: add Slack/Teams/Email/Webhook; run **health**; rotate secrets. -* **Notifications → Rules**: create/edit YAML rules with linting; test with sample events; see match rate. -* **Notifications → Deliveries**: timeline with filters (status, channel, rule); inspect last error; retry. -* **Digest preview**: shows current window contents and when it will flush. -* **Quiet hours**: configure per tenant; show overrides. -* **DLQ**: browse dead‑letters; requeue after fix. - ---- - -## 15) Failure modes & responses - -| Condition | Behavior | -| ----------------------------------- | ------------------------------------------------------------------------------------- | -| Slack 429 / Teams 429 | Respect `Retry‑After`, backoff with jitter, reduce concurrency | -| SMTP transient 4xx | Retry up to `maxAttempts`; escalate to DLQ on exhaust | -| Invalid channel secret | Mark channel unhealthy; suppress sends; surface in UI | -| Rule explosion (matches everything) | Safety valve: per‑tenant RPM caps; auto‑pause rule after X drops; UI alert | -| Bus outage | Buffer to local queue (bounded); resume consuming when healthy | -| Mongo slowness | Fall back to Redis throttles; batch write deliveries; shed low‑priority notifications | - ---- - -## 16) Testing matrix - -* **Unit**: matchers, throttle math, digest coalescing, idempotency keys, template rendering edge cases. -* **Connectors**: provider‑level rate limits, payload size truncation, error mapping. -* **Integration**: synthetic event storm (10k/min), ensure p95 latency & duplicate rate. -* **Security**: DPoP/mTLS on APIs; secretRef resolution; webhook signing & replay windows. -* **i18n**: localized templates render deterministically. -* **Chaos**: Slack/Teams API flaps; SMTP greylisting; Redis hiccups; ensure graceful degradation. - ---- - -## 17) Sequences (representative) - -**A) New criticals after Feedser delta (Slack immediate + Email hourly digest)** - -```mermaid -sequenceDiagram - autonumber - participant SCH as Scheduler - participant NO as Notify.Worker - participant SL as Slack - participant SMTP as Email - - SCH->>NO: bus event scheduler.rescan.delta { newCritical:1, digest:sha256:... } - NO->>NO: match rules (Slack immediate; Email hourly digest) - NO->>SL: chat.postMessage (concise) - SL-->>NO: 200 OK - NO->>NO: append to digest window (email:soc) - Note over NO: At window close → render digest email - NO->>SMTP: send email (detailed digest) - SMTP-->>NO: 250 OK -``` - -**B) Admission deny (Teams card + Webhook)** - -```mermaid -sequenceDiagram - autonumber - participant ZA as Zastava - participant NO as Notify.Worker - participant TE as Teams - participant WH as Webhook - - ZA->>NO: bus event zastava.admission { decision: "deny", reasons: [...] } - NO->>TE: POST adaptive card - TE-->>NO: 200 OK - NO->>WH: POST JSON (signed) - WH-->>NO: 2xx -``` - ---- - -## 18) Implementation notes - -* **Language**: .NET 10; minimal API; `System.Text.Json` with canonical writer for body hashing; Channels for pipelines. -* **Bus**: Redis Streams (**XGROUP** consumers) or NATS JetStream for at‑least‑once with ack; per‑tenant consumer groups to localize backpressure. -* **Templates**: compile and cache per rule+channel+locale; version with rule `updatedAt` to invalidate. -* **Rules**: store raw YAML + parsed AST; validate with schema + static checks (e.g., nonsensical combos). -* **Secrets**: pluggable secret resolver (Authority Secret proxy, K8s, Vault). -* **Rate limiting**: `System.Threading.RateLimiting` + per‑connector adapters. - ---- - -## 19) Roadmap (post‑v1) - -* **PagerDuty/Opsgenie** connectors; **Jira** ticket creation. -* **User inbox** (in‑app notifications) + mobile push via webhook relay. -* **Anomaly suppression**: auto‑pause noisy rules with hints (learned thresholds). -* **Graph rules**: “only notify if *not_affected → affected* transition at consensus layer”. -* **Label enrichment**: pluggable taggers (business criticality, data classification) to refine matchers. + +* **Rules** + + * `POST /rules` | `GET /rules` | `GET /rules/{id}` | `PATCH /rules/{id}` | `DELETE /rules/{id}` + * `POST /rules/{id}/test` → dry‑run rule against a **sample event** (no delivery unless `--send`) + +* **Deliveries** + + * `POST /deliveries` → ingest worker delivery state (idempotent via `deliveryId`). + * `GET /deliveries?since=...&status=...&limit=...` → list envelope `{ items, count, continuationToken }` (most recent first); base metadata keys match the test-send response (`channelType`, `target`, `previewProvider`, `traceId`); rate-limited via `api.rateLimits.deliveryHistory`. See `docs/modules/notify/resources/samples/notify-delivery-list-response.sample.json`. + * `GET /deliveries/{id}` → detail (redacted body + metadata) + * `POST /deliveries/{id}/retry` → force retry (admin, future sprint) + +* **Admin** + + * `GET /stats` (per tenant counts, last hour/day) + * `GET /healthz|readyz` (liveness) + * `POST /locks/acquire` | `POST /locks/release` – worker coordination primitives (short TTL). + * `POST /digests` | `GET /digests/{actionKey}` | `DELETE /digests/{actionKey}` – manage open digest windows. + * `POST /audit` | `GET /audit?since=&limit=` – append/query structured audit trail entries. + +**Ingestion**: workers do **not** expose public ingestion; they **subscribe** to the internal bus. (Optional `/events/test` for integration testing, admin‑only.) + +--- + +## 9) Delivery pipeline (worker) + +``` +[Event bus] → [Ingestor] → [RuleMatcher] → [Throttle/Dedupe] → [DigestCoalescer] → [Renderer] → [Connector] → [Result] + └────────→ [DeliveryStore] +``` + +* **Ingestor**: N consumers with per‑key ordering (key = tenant|digest|namespace). +* **RuleMatcher**: loads active rules snapshot for tenant into memory; vectorized predicate check. +* **Throttle/Dedupe**: consult Redis + Mongo `throttles`; if hit → record `status=throttled`. +* **DigestCoalescer**: append to open digest window or flush when timer expires. +* **Renderer**: select template (channel+locale), inject variables, enforce length limits, compute `bodyHash`. +* **Connector**: send; handle provider‑specific rate limits and backoffs; `maxAttempts` with exponential jitter; overflow → DLQ (dead‑letter topic) + UI surfacing. + +**Idempotency**: per action **idempotency key** stored in Redis (TTL = `throttle window` or `digest window`). Connectors also respect **provider** idempotency where available (e.g., Slack `client_msg_id`). + +--- + +## 10) Reliability & rate controls + +* **Per‑tenant** RPM caps (default 600/min) + **per‑channel** concurrency (Slack 1–4, Teams 1–2, Email 8–32 based on relay). +* **Backoff** map: Slack 429 → respect `Retry‑After`; SMTP 4xx → retry; 5xx → retry with jitter; permanent rejects → drop with status recorded. +* **DLQ**: NATS/Redis stream `notify.dlq` with `{event, rule, action, error}` for operator inspection; UI shows DLQ items. + +--- + +## 11) Security & privacy + +* **AuthZ**: all APIs require **Authority** OpToks; actions scoped by tenant. +* **Secrets**: `secretRef` only; Notify fetches just‑in‑time from Authority Secret proxy or K8s Secret (mounted). No plaintext secrets in Mongo. +* **Egress TLS**: validate SSL; pin domains per channel config; optional CA bundle override for on‑prem SMTP. +* **Webhook signing**: HMAC or Ed25519 signatures in `X-StellaOps-Signature` + replay‑window timestamp; include canonical body hash in header. +* **Redaction**: deliveries store **hashes** of bodies, not full payloads for chat/email to minimize PII retention (configurable). +* **Quiet hours**: per tenant (e.g., 22:00–06:00) route high‑sev only; defer others to digests. +* **Loop prevention**: Webhook target allowlist + event origin tags; do not ingest own webhooks. + +--- + +## 12) Observability (Prometheus + OTEL) + +* `notify.events_consumed_total{kind}` +* `notify.rules_matched_total{ruleId}` +* `notify.throttled_total{reason}` +* `notify.digest_coalesced_total{window}` +* `notify.sent_total{channel}` / `notify.failed_total{channel,code}` +* `notify.delivery_latency_seconds{channel}` (end‑to‑end) +* **Tracing**: spans `ingest`, `match`, `render`, `send`; correlation id = `eventId`. + +**SLO targets** + +* Event→delivery p95 **≤ 30–60 s** under nominal load. +* Failure rate p95 **< 0.5%** per hour (excluding provider outages). +* Duplicate rate **≈ 0** (idempotency working). + +--- + +## 13) Configuration (YAML) + +```yaml +notify: + authority: + issuer: "https://authority.internal" + require: "dpop" # or "mtls" + bus: + kind: "redis" # or "nats" + streams: + - "scanner.events" + - "scheduler.events" + - "attestor.events" + - "zastava.events" + mongo: + uri: "mongodb://mongo/notify" + limits: + perTenantRpm: 600 + perChannel: + slack: { concurrency: 2 } + teams: { concurrency: 1 } + email: { concurrency: 8 } + webhook: { concurrency: 8 } + digests: + defaultWindow: "1h" + maxItems: 100 + quietHours: + enabled: true + window: "22:00-06:00" + minSeverity: "critical" + webhooks: + sign: + method: "ed25519" # or "hmac-sha256" + keyRef: "ref://notify/webhook-sign-key" +``` + +--- + +## 14) UI touch‑points + +* **Notifications → Channels**: add Slack/Teams/Email/Webhook; run **health**; rotate secrets. +* **Notifications → Rules**: create/edit YAML rules with linting; test with sample events; see match rate. +* **Notifications → Deliveries**: timeline with filters (status, channel, rule); inspect last error; retry. +* **Digest preview**: shows current window contents and when it will flush. +* **Quiet hours**: configure per tenant; show overrides. +* **DLQ**: browse dead‑letters; requeue after fix. + +--- + +## 15) Failure modes & responses + +| Condition | Behavior | +| ----------------------------------- | ------------------------------------------------------------------------------------- | +| Slack 429 / Teams 429 | Respect `Retry‑After`, backoff with jitter, reduce concurrency | +| SMTP transient 4xx | Retry up to `maxAttempts`; escalate to DLQ on exhaust | +| Invalid channel secret | Mark channel unhealthy; suppress sends; surface in UI | +| Rule explosion (matches everything) | Safety valve: per‑tenant RPM caps; auto‑pause rule after X drops; UI alert | +| Bus outage | Buffer to local queue (bounded); resume consuming when healthy | +| Mongo slowness | Fall back to Redis throttles; batch write deliveries; shed low‑priority notifications | + +--- + +## 16) Testing matrix + +* **Unit**: matchers, throttle math, digest coalescing, idempotency keys, template rendering edge cases. +* **Connectors**: provider‑level rate limits, payload size truncation, error mapping. +* **Integration**: synthetic event storm (10k/min), ensure p95 latency & duplicate rate. +* **Security**: DPoP/mTLS on APIs; secretRef resolution; webhook signing & replay windows. +* **i18n**: localized templates render deterministically. +* **Chaos**: Slack/Teams API flaps; SMTP greylisting; Redis hiccups; ensure graceful degradation. + +--- + +## 17) Sequences (representative) + +**A) New criticals after Feedser delta (Slack immediate + Email hourly digest)** + +```mermaid +sequenceDiagram + autonumber + participant SCH as Scheduler + participant NO as Notify.Worker + participant SL as Slack + participant SMTP as Email + + SCH->>NO: bus event scheduler.rescan.delta { newCritical:1, digest:sha256:... } + NO->>NO: match rules (Slack immediate; Email hourly digest) + NO->>SL: chat.postMessage (concise) + SL-->>NO: 200 OK + NO->>NO: append to digest window (email:soc) + Note over NO: At window close → render digest email + NO->>SMTP: send email (detailed digest) + SMTP-->>NO: 250 OK +``` + +**B) Admission deny (Teams card + Webhook)** + +```mermaid +sequenceDiagram + autonumber + participant ZA as Zastava + participant NO as Notify.Worker + participant TE as Teams + participant WH as Webhook + + ZA->>NO: bus event zastava.admission { decision: "deny", reasons: [...] } + NO->>TE: POST adaptive card + TE-->>NO: 200 OK + NO->>WH: POST JSON (signed) + WH-->>NO: 2xx +``` + +--- + +## 18) Implementation notes + +* **Language**: .NET 10; minimal API; `System.Text.Json` with canonical writer for body hashing; Channels for pipelines. +* **Bus**: Redis Streams (**XGROUP** consumers) or NATS JetStream for at‑least‑once with ack; per‑tenant consumer groups to localize backpressure. +* **Templates**: compile and cache per rule+channel+locale; version with rule `updatedAt` to invalidate. +* **Rules**: store raw YAML + parsed AST; validate with schema + static checks (e.g., nonsensical combos). +* **Secrets**: pluggable secret resolver (Authority Secret proxy, K8s, Vault). +* **Rate limiting**: `System.Threading.RateLimiting` + per‑connector adapters. + +--- + +## 19) Roadmap (post‑v1) + +* **PagerDuty/Opsgenie** connectors; **Jira** ticket creation. +* **User inbox** (in‑app notifications) + mobile push via webhook relay. +* **Anomaly suppression**: auto‑pause noisy rules with hints (learned thresholds). +* **Graph rules**: “only notify if *not_affected → affected* transition at consensus layer”. +* **Label enrichment**: pluggable taggers (business criticality, data classification) to refine matchers. diff --git a/docs/modules/notify/implementation_plan.md b/docs/modules/notify/implementation_plan.md new file mode 100644 index 00000000..8d3d72b8 --- /dev/null +++ b/docs/modules/notify/implementation_plan.md @@ -0,0 +1,61 @@ +# Implementation plan — Notify + +## Delivery phases +- **Phase 1 – Core rules engine & delivery ledger** + Implement rules/channels schema, event ingestion, rule evaluation, idempotent deliveries, and audit logging. +- **Phase 2 – Connectors & rendering** + Ship Slack/Teams/Email/Webhook connectors, template rendering, localization, throttling, retries, and secret referencing. +- **Phase 3 – Console & CLI authoring** + Provide UI/CLI for rule authoring, previews, channel health, delivery browsing, digests, and test sends. +- **Phase 4 – Governance & observability** + Add approvals, RBAC, tenant quotas, Notify metrics/logs/traces, dashboards, Notify-specific alerts, and Notify runbooks. +- **Phase 5 – Offline & compliance** + Produce Offline Kit bundles (rules/channels/deploy scripts), signed exports, retention policies, and auditing for regulated environments. + +## Work breakdown +- **Service & worker** + - REST API for rules/channels/delivery history, idempotency middleware, digest scheduler. + - Worker pipelines for event intake, rule matching, template rendering, delivery execution, retries, and throttling. + - Delivery ledger capturing payload metadata, response, retry state, DSSE signatures. +- **Connectors** + - Slack/Teams/Email/Webhook plug-ins with configuration validation, rate limiting, error classification. + - Secrets referenced via Authority/Secret store; no plaintext storage. +- **Console & CLI** + - Console module for rules builder, condition editor, preview, test send, delivery insights, digests and schedule configuration. + - CLI (`stella notify rule|channel|delivery`) for automation, export/import. +- **Integrations** + - Event sources: Concelier, Excititor, Policy Engine, Vuln Explorer, Export Center, Attestor, Zastava, Scheduler. + - Notify events to Notify (meta) for failure escalations, accepted-risk expiration reminders. +- **Observability & ops** + - Metrics: delivery success/failure, retry counts, throttle hits, digest generation, channel health. + - Logs/traces with tenant, rule ID, channel, correlation ID; dashboards and alerts. + - Runbooks for misconfigured channels, throttling, event backlog, incident digest. +- **Docs & compliance** + - Update Notifications Studio guides, channel runbooks, security/RBAC docs, Offline Kit instructions. + - Provide compliance checklist (audit logging, retention, opt-out). + +## Acceptance criteria +- Rules evaluate deterministically per event; deliveries idempotent with audit trail and DSSE signatures. +- Channel connectors support retries, rate limits, health checks, previews; secrets referenced securely. +- Console/CLI support rule creation, testing, digests, delivery browsing, and export/import workflows. +- Observability dashboards track delivery health; alerts fire for sustained failures or backlog; runbooks cover remediation. +- Offline Kit bundle contains configs, rules, digests, and deployment scripts for air-gapped installs. +- Notify respects tenancy and RBAC; governance (approvals, change log) enforced for high-impact rules. + +## Risks & mitigations +- **Notification storms:** throttling, digests, dedupe windows, preview/test gating. +- **Secret compromise:** secret references only, rotation workflows, audit logging. +- **Connector API changes:** versioned adapter layer, nightly health checks, fallback channels. +- **Noise vs signal:** simulation previews, metrics, rule scoring, recommended defaults. +- **Offline parity:** export/import of rules, connectors, and digests with signed manifests. + +## Test strategy +- **Unit:** rule evaluation, template rendering, connector clients, throttling, digests. +- **Integration:** end-to-end events from core services, multi-channel routing, retries, audit logging. +- **Performance:** burst throttling, digest creation, large rule sets. +- **Security:** RBAC tests, tenant isolation, secret reference validation, DSSE signature verification. +- **Offline:** export/import round-trips, Offline Kit deployment, manual delivery replay. + +## Definition of done +- Notify service, workers, connectors, Console/CLI, observability, and Offline Kit assets shipped with documentation and runbooks. +- Compliance checklist appended to docs; ./TASKS.md and ../../TASKS.md updated with progress. diff --git a/docs/notify/samples/notify-channel@1.sample.json b/docs/modules/notify/resources/samples/notify-channel@1.sample.json similarity index 100% rename from docs/notify/samples/notify-channel@1.sample.json rename to docs/modules/notify/resources/samples/notify-channel@1.sample.json diff --git a/docs/notify/samples/notify-delivery-list-response.sample.json b/docs/modules/notify/resources/samples/notify-delivery-list-response.sample.json similarity index 100% rename from docs/notify/samples/notify-delivery-list-response.sample.json rename to docs/modules/notify/resources/samples/notify-delivery-list-response.sample.json diff --git a/docs/notify/samples/notify-event@1.sample.json b/docs/modules/notify/resources/samples/notify-event@1.sample.json similarity index 100% rename from docs/notify/samples/notify-event@1.sample.json rename to docs/modules/notify/resources/samples/notify-event@1.sample.json diff --git a/docs/notify/samples/notify-rule@1.sample.json b/docs/modules/notify/resources/samples/notify-rule@1.sample.json similarity index 100% rename from docs/notify/samples/notify-rule@1.sample.json rename to docs/modules/notify/resources/samples/notify-rule@1.sample.json diff --git a/docs/notify/samples/notify-template@1.sample.json b/docs/modules/notify/resources/samples/notify-template@1.sample.json similarity index 100% rename from docs/notify/samples/notify-template@1.sample.json rename to docs/modules/notify/resources/samples/notify-template@1.sample.json diff --git a/docs/notify/schemas/notify-channel@1.json b/docs/modules/notify/resources/schemas/notify-channel@1.json similarity index 100% rename from docs/notify/schemas/notify-channel@1.json rename to docs/modules/notify/resources/schemas/notify-channel@1.json diff --git a/docs/notify/schemas/notify-event@1.json b/docs/modules/notify/resources/schemas/notify-event@1.json similarity index 100% rename from docs/notify/schemas/notify-event@1.json rename to docs/modules/notify/resources/schemas/notify-event@1.json diff --git a/docs/notify/schemas/notify-rule@1.json b/docs/modules/notify/resources/schemas/notify-rule@1.json similarity index 100% rename from docs/notify/schemas/notify-rule@1.json rename to docs/modules/notify/resources/schemas/notify-rule@1.json diff --git a/docs/notify/schemas/notify-template@1.json b/docs/modules/notify/resources/schemas/notify-template@1.json similarity index 100% rename from docs/notify/schemas/notify-template@1.json rename to docs/modules/notify/resources/schemas/notify-template@1.json diff --git a/docs/modules/orchestrator/AGENTS.md b/docs/modules/orchestrator/AGENTS.md new file mode 100644 index 00000000..a49f979e --- /dev/null +++ b/docs/modules/orchestrator/AGENTS.md @@ -0,0 +1,22 @@ +# Source & Job Orchestrator agent guide + +## Mission +The Orchestrator schedules, observes, and recovers ingestion and analysis jobs across the StellaOps platform. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Read the design summaries in ./architecture.md (quota governance, job lifecycle, dashboard feeds). +2. Open ../../implplan/SPRINTS.md and locate stories for this component. +3. Check ./TASKS.md and update status before/after work. +4. Review ./README.md for responsibilities and ensure changes maintain determinism and offline parity. + +## Guardrails +- Uphold Aggregation-Only Contract boundaries when consuming ingestion data. +- Preserve determinism and provenance in all derived outputs. +- Document offline/air-gap pathways for any new feature. +- Update telemetry/observability assets alongside feature work. \ No newline at end of file diff --git a/docs/modules/orchestrator/README.md b/docs/modules/orchestrator/README.md new file mode 100644 index 00000000..1cd9a7bc --- /dev/null +++ b/docs/modules/orchestrator/README.md @@ -0,0 +1,29 @@ +# StellaOps Source & Job Orchestrator + +The Orchestrator schedules, observes, and recovers ingestion and analysis jobs across the StellaOps platform. + +## Responsibilities +- Track job state, throughput, and errors for Concelier, Excititor, Scheduler, and export pipelines. +- Expose dashboards and APIs for throttling, replays, and failover. +- Enforce rate-limits, concurrency and dependency chains across queues. +- Stream structured events and audit logs for incident response. + +## Key components +- Orchestrator WebService (control plane). +- Queue adapters (Redis/NATS) and job ledger. +- Console dashboard module and CLI integration for operators. + +## Integrations & dependencies +- Authority for authN/Z on operational actions. +- Telemetry stack for job metrics and alerts. +- Scheduler/Concelier/Excititor workers for job lifecycle. +- Offline Kit for state export/import during air-gap refreshes. + +## Operational notes +- Job recovery runbooks and dashboard JSON as described in Epic 9. +- Audit retention policies for job history. +- Rate-limit reconfiguration guidelines. + +## Epic alignment +- Epic 9: Source & Job Orchestrator Dashboard. +- ORCH stories in ../../TASKS.md. diff --git a/docs/modules/orchestrator/TASKS.md b/docs/modules/orchestrator/TASKS.md new file mode 100644 index 00000000..f7cb1139 --- /dev/null +++ b/docs/modules/orchestrator/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Source & Job Orchestrator + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| SOURCE---JOB-ORCHESTRATOR-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Ensure ./README.md reflects the latest epic deliverables. | Align with ./AGENTS.md | +| SOURCE---JOB-ORCHESTRATOR-ENG-0001 | TODO | Module Team | Break down epic milestones into actionable stories. | Sync into ../../TASKS.md | +| SOURCE---JOB-ORCHESTRATOR-OPS-0001 | TODO | Ops Guild | Prepare runbooks/observability assets once MVP lands. | Document outputs in ./README.md | diff --git a/docs/modules/orchestrator/architecture.md b/docs/modules/orchestrator/architecture.md new file mode 100644 index 00000000..a431ca47 --- /dev/null +++ b/docs/modules/orchestrator/architecture.md @@ -0,0 +1,52 @@ +# Source & Job Orchestrator architecture + +> Based on Epic 9 – Source & Job Orchestrator Dashboard; this section outlines components, job lifecycle, rate-limit governance, and observability. + +## 1) Topology + +- **Orchestrator API (`StellaOps.Orchestrator`).** Minimal API providing job state, throttling controls, replay endpoints, and dashboard data. Authenticated via Authority scopes (`orchestrator:*`). +- **Job ledger (Mongo).** Collections `jobs`, `job_history`, `sources`, `quotas`, `throttles`, `incidents`. Append-only history ensures auditability. +- **Queue abstraction.** Supports Mongo queue, Redis Streams, or NATS JetStream (pluggable). Each job carries lease metadata and retry policy. +- **Dashboard feeds.** SSE/GraphQL endpoints supply Console UI with job timelines, throughput, error distributions, and rate-limit status. + +## 2) Job lifecycle + +1. **Enqueue.** Producer services (Concelier, Excititor, Scheduler, Export Center, Policy Engine) submit `JobRequest` records containing `jobType`, `tenant`, `priority`, `payloadDigest`, `dependencies`. +2. **Scheduling.** Orchestrator applies quotas and rate limits per `{tenant, jobType}`. Jobs exceeding limits are staged in pending queue with next eligible timestamp. +3. **Leasing.** Workers poll `LeaseJob` endpoint; Orchestrator returns job with `leaseId`, `leaseUntil`, and instrumentation tokens. Lease renewal required for long-running tasks. +4. **Completion.** Worker reports status (`succeeded`, `failed`, `canceled`, `timed_out`). On success the job is archived; on failure Orchestrator applies retry policy (exponential backoff, max attempts). Incidents escalate to Ops if thresholds exceeded. +5. **Replay.** Operators trigger `POST /jobs/{id}/replay` which clones job payload, sets `replayOf` pointer, and requeues with high priority while preserving determinism metadata. + +## 3) Rate-limit & quota governance + +- Quotas defined per tenant/profile (`maxActive`, `maxPerHour`, `burst`). Stored in `quotas` and enforced before leasing. +- Dynamic throttles allow ops to pause specific sources (`pauseSource`, `resumeSource`) or reduce concurrency. +- Circuit breakers automatically pause job types when failure rate > configured threshold; incidents generated via Notify and Observability stack. + +## 4) APIs + +- `GET /api/jobs?status=` — list jobs with filters (tenant, jobType, status, time window). +- `GET /api/jobs/{id}` — job detail (payload digest, attempts, worker, lease history, metrics). +- `POST /api/jobs/{id}/cancel` — cancel running/pending job with audit reason. +- `POST /api/jobs/{id}/replay` — schedule replay. +- `POST /api/limits/throttle` — apply throttle (requires elevated scope). +- `GET /api/dashboard/metrics` — aggregated metrics for Console dashboards. + +All responses include deterministic timestamps, job digests, and DSSE signature fields for offline reconciliation. + +## 5) Observability + +- Metrics: `job_queue_depth{jobType,tenant}`, `job_latency_seconds`, `job_failures_total`, `job_retry_total`, `lease_extensions_total`. +- Logs: structured with `jobId`, `jobType`, `tenant`, `workerId`, `leaseId`, `status`. Incident logs flagged for Ops. +- Traces: spans covering `enqueue`, `schedule`, `lease`, `worker_execute`, `complete`. Trace IDs propagate to worker spans for end-to-end correlation. + +## 6) Offline support + +- Orchestrator exports audit bundles: `jobs.jsonl`, `history.jsonl`, `throttles.jsonl`, `manifest.json`, `signatures/`. Used for offline investigations and compliance. +- Replay manifests contain job digests and success/failure notes for deterministic proof. + +## 7) Operational considerations + +- HA deployment with multiple API instances; queue storage determines redundancy strategy. +- Support for `maintenance` mode halting leases while allowing status inspection. +- Runbook includes procedures for expanding quotas, blacklisting misbehaving tenants, and recovering stuck jobs (clearing leases, applying pause/resume). diff --git a/docs/modules/orchestrator/implementation_plan.md b/docs/modules/orchestrator/implementation_plan.md new file mode 100644 index 00000000..4f369df3 --- /dev/null +++ b/docs/modules/orchestrator/implementation_plan.md @@ -0,0 +1,62 @@ +# Implementation plan — Source & Job Orchestrator + +## Delivery phases +- **Phase 1 – Core service & job ledger** + Implement source registry, run/job tables, queue abstraction, lease management, token-bucket rate limiting, watchdogs, and API primitives (`/sources`, `/runs`, `/jobs`). +- **Phase 2 – Worker SDK & artifact registry** + Embed worker SDK in Conseiller, Excititor, SBOM, Policy Engine; capture artifact metadata + hashes, enforce idempotency, publish progress/metrics. +- **Phase 3 – Observability & dashboard** + Ship metrics, traces, incident logging, SSE/WebSocket feeds, and Console dashboard (DAG/timeline, heatmaps, error clustering, SLO burn rate). +- **Phase 4 – Controls & resilience** + Deliver pause/resume/throttle/retry/backfill tooling, dead-letter review, circuit breakers, blackouts, backpressure handling, and automation hooks. +- **Phase 5 – Offline & compliance** + Generate deterministic audit bundles (`jobs.jsonl`, `history.jsonl`, `throttles.jsonl`), provenance manifests, and offline replay scripts. + +## Work breakdown +- **Service & persistence** + - Postgres schema (`sources`, `runs`, `jobs`, `artifacts`, `dag_edges`, `quotas`, `schedules`, `incidents`). + - Lease manager with heartbeats, retries, and dead-letter queues. + - Token-bucket rate limiter per `{tenant, source.host}`; adaptive refill on upstream throttles. + - Watermark/backfill orchestration for event-time windows. +- **Worker SDK** + - Claim/heartbeat/report contract, deterministic artifact hashing, idempotency enforcement. + - Library release for .NET workers plus language bindings for Rust/Go ingestion agents. +- **Control plane APIs** + - CRUD for sources, runs, jobs, quotas, schedules; control actions (retry, cancel, prioritize, pause/resume, backfill). + - SSE/WebSocket stream for Console updates. +- **Observability** + - Metrics: queue depth, job latency, failure classes, rate-limit hits, burn rate. + - Error clustering (HTTP 429/5xx, schema mismatch, parse errors), incident logging with reason codes. + - Gantt timeline and DAG JSON for Console visualisation. +- **Console & CLI** + - Console app sections: overview, sources, runs, job detail, incidents, throttles. + - CLI commands: `stella orchestrator sources|runs|jobs|throttle|backfill`. +- **Compliance & offline** + - Immutable audit bundles with signatures; exports via Export Center; Offline Kit instructions. + - Tenant isolation validation and secret redaction for logs/UI. + +## Acceptance criteria +- Orchestrator schedules all advisory/VEX/SBOM/policy jobs with quotas, rate limits, and idempotency; retries and replay preserve provenance. +- Console dashboard reflects real-time DAG status, queue depth, SLO burn rate, and allows pause/resume/throttle/backfill with audit trail. +- Worker SDK integrated across producer services, emitting progress and artifact metadata. +- Observability stack exposes metrics, logs, traces, incidents, and alerts for stuck jobs, throttling, and failure spikes. +- Offline audit bundles reproduce job history deterministically and verify signatures. + +## Risks & mitigations +- **Backpressure/queue overload:** adaptive token buckets, circuit breakers, dynamic concurrency; degrade gracefully. +- **Upstream vendor throttles:** throttle management with user-visible state, automatic jitter and retry. +- **Tenant leakage:** enforce tenant filters at API/queue/storage, fuzz tests, redaction. +- **Complex DAG errors:** built-in diagnostics, error clustering, partial replay tooling. +- **Operator error:** confirmation prompts, RBAC, runbook guidance, reason codes logged. + +## Test strategy +- **Unit:** scheduling, quota enforcement, lease renewals, token bucket, watermark arithmetic. +- **Integration:** worker SDK with Conseiller/Excititor/SBOM pipelines, pause/resume/backfill flows, failure recovery. +- **Performance:** high-volume job workloads, queue backpressure, concurrency caps, dashboard SSE load tests. +- **Chaos:** simulate upstream outages, stuck workers, clock skew, Postgres failover. +- **Compliance:** audit bundle generation, signature verification, offline replay. + +## Definition of done +- All phases delivered with telemetry, dashboards, and runbooks published. +- Console + CLI parity validated; Offline Kit instructions complete. +- ./TASKS.md and ../../TASKS.md updated with status; documentation (README/architecture/this plan) reflects latest behaviour. diff --git a/docs/modules/platform/AGENTS.md b/docs/modules/platform/AGENTS.md new file mode 100644 index 00000000..8994db3a --- /dev/null +++ b/docs/modules/platform/AGENTS.md @@ -0,0 +1,22 @@ +# Platform agent guide + +## Mission +Platform module describes cross-cutting architecture, contracts, and guardrails that bind the services together. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/platform/README.md b/docs/modules/platform/README.md new file mode 100644 index 00000000..f88ecd6a --- /dev/null +++ b/docs/modules/platform/README.md @@ -0,0 +1,29 @@ +# StellaOps Platform + +Platform module describes cross-cutting architecture, contracts, and guardrails that bind the services together. + +## Responsibilities +- Maintain the system-wide architecture overview and integration diagrams. +- Capture Aggregation-Only Contract guidance and migration playbooks. +- Document shared services such as API gateway, tenancy, quotas, and offline posture. +- Coordinate platform-wide epics and compliance checklists. + +## Key components +- Architecture overview in ./architecture-overview.md. +- References to high-level docs (../../07_HIGH_LEVEL_ARCHITECTURE.md). + +## Integrations & dependencies +- All StellaOps services via shared contracts (AOC, telemetry, security). +- DevOps for release governance. +- Docs guild for cross-module onboarding. + +## Operational notes +- No runtime component; focus is architectural governance. +- Glossaries and guardrails cross-linked across docs. + +## Backlog references +- DOCS-AOC-19-002/003 in ../../TASKS.md. +- Future platform epics under docs/implplan/SPRINTS.md. + +## Epic alignment +- Aligns with the Aggregation-Only Contract reference, Policy and Policy Studio guides, Graph/Vulnerability Explorer documentation, and the Orchestrator, Advisory AI, and Notifications implementation plans to keep platform guardrails consistent across services. diff --git a/docs/modules/platform/TASKS.md b/docs/modules/platform/TASKS.md new file mode 100644 index 00000000..a61f2c90 --- /dev/null +++ b/docs/modules/platform/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Platform + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| PLATFORM-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| PLATFORM-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| PLATFORM-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/architecture/overview.md b/docs/modules/platform/architecture-overview.md similarity index 90% rename from docs/architecture/overview.md rename to docs/modules/platform/architecture-overview.md index c28663f1..568de1c8 100644 --- a/docs/architecture/overview.md +++ b/docs/modules/platform/architecture-overview.md @@ -1,168 +1,168 @@ -# StellaOps Architecture Overview (Sprint 19) - -> **Ownership:** Architecture Guild • Docs Guild -> **Audience:** Service owners, platform engineers, solution architects -> **Related:** [High-Level Architecture](../07_HIGH_LEVEL_ARCHITECTURE.md), [Concelier Architecture](../ARCHITECTURE_CONCELIER.md), [Policy Engine Architecture](policy-engine.md), [Aggregation-Only Contract](../ingestion/aggregation-only-contract.md) - -This dossier summarises the end-to-end runtime topology after the Aggregation-Only Contract (AOC) rollout. It highlights where raw facts live, how ingest services enforce guardrails, and how downstream components consume those facts to derive policy decisions and user-facing experiences. - ---- - -## 1 · System landscape - -```mermaid -graph TD - subgraph Edge["Clients & Automation"] - CLI[stella CLI] - UI[Console SPA] - APIClients[CI / API Clients] - end - Gateway[API Gateway
(JWT + DPoP scopes)] - subgraph Scanner["Fact Collection"] - ScannerWeb[Scanner.WebService] - ScannerWorkers[Scanner.Workers] - Agent[Agent Runtime] - end - subgraph Ingestion["Aggregation-Only Ingestion (AOC)"] - Concelier[Concelier.WebService] - Excititor[Excititor.WebService] - RawStore[(MongoDB
advisory_raw / vex_raw)] - end - subgraph Derivation["Policy & Overlay"] - Policy[Policy Engine] - Scheduler[Scheduler Services] - Notify[Notifier] - end - subgraph Experience["UX & Export"] - UIService[Console Backend] - Exporters[Export / Offline Kit] - end - Observability[Telemetry Stack] - - CLI --> Gateway - UI --> Gateway - APIClients --> Gateway - Gateway --> ScannerWeb - ScannerWeb --> ScannerWorkers - ScannerWorkers --> Concelier - ScannerWorkers --> Excititor - Concelier --> RawStore - Excititor --> RawStore - RawStore --> Policy - Policy --> Scheduler - Policy --> Notify - Policy --> UIService - Scheduler --> UIService - UIService --> Exporters - Exporters --> CLI - Exporters --> Offline[Offline Kit] - Observability -.-> ScannerWeb - Observability -.-> Concelier - Observability -.-> Excititor - Observability -.-> Policy - Observability -.-> Scheduler - Observability -.-> Notify -``` - -Key boundaries: - -- **AOC border.** Everything inside the Ingestion subgraph writes only immutable raw facts plus link hints. Derived severity, consensus, and risk remain outside the border. -- **Policy-only derivation.** Policy Engine materialises `effective_finding_*` collections and emits overlays; other services consume but never mutate them. -- **Tenant enforcement.** Authority-issued DPoP scopes flow through Gateway to every service; raw stores and overlays include `tenant` strictly. - ---- - -## 2 · Aggregation-Only Contract focus - -### 2.1 Responsibilities at the boundary - -| Area | Services | Responsibilities under AOC | Forbidden under AOC | -|------|----------|-----------------------------|---------------------| -| **Ingestion (Concelier / Excititor)** | `StellaOps.Concelier.WebService`, `StellaOps.Excititor.WebService` | Fetch upstream advisories/VEX, verify signatures, compute linksets, append immutable documents to `advisory_raw` / `vex_raw`, emit observability signals, expose raw read APIs. | Computing severity, consensus, suppressions, or policy hints; merging upstream sources into a single derived record; mutating existing documents. | -| **Policy & Overlay** | `StellaOps.Policy.Engine`, Scheduler | Join SBOM inventory with raw advisories/VEX, evaluate policies, issue `effective_finding_*` overlays, drive remediation workflows. | Writing to raw collections; bypassing guard scopes; running without recorded provenance. | -| **Experience layers** | Console, CLI, Exporters | Surface raw facts + policy overlays; run `stella aoc verify`; render AOC dashboards and reports. | Accepting ingestion payloads that lack provenance or violate guard results. | - -### 2.2 Raw stores - -| Collection | Purpose | Key fields | Notes | -|------------|---------|------------|-------| -| `advisory_raw` | Immutable vendor/ecosystem advisory documents. | `_id`, `tenant`, `source.*`, `upstream.*`, `content.raw`, `linkset`, `supersedes`. | Idempotent by `(source.vendor, upstream.upstream_id, upstream.content_hash)`. | -| `vex_raw` | Immutable vendor VEX statements. | Mirrors `advisory_raw`; `identifiers.statements` summarises affected components. | Maintains supersedes chain identical to advisory flow. | -| Change streams (`advisory_raw_stream`, `vex_raw_stream`) | Feed Policy Engine and Scheduler. | `operationType`, `documentKey`, `fullDocument`, `tenant`, `traceId`. | Scope filtered per tenant before delivery. | - -### 2.3 Guarded ingestion sequence - -```mermaid -sequenceDiagram - participant Upstream as Upstream Source - participant Connector as Concelier/Excititor Connector - participant Guard as AOCWriteGuard - participant Mongo as MongoDB (advisory_raw / vex_raw) - participant Stream as Change Stream - participant Policy as Policy Engine - - Upstream-->>Connector: CSAF / OSV / VEX document - Connector->>Connector: Normalize transport, compute content_hash - Connector->>Guard: Candidate raw doc (source + upstream + content + linkset) - Guard-->>Connector: ERR_AOC_00x on violation - Guard->>Mongo: Append immutable document (with tenant & supersedes) - Mongo-->>Stream: Change event (tenant scoped) - Stream->>Policy: Raw delta payload - Policy->>Policy: Evaluate policies, compute effective findings -``` - ---- - -### 2.4 Authority scopes & tenancy - -| Scope | Holder | Purpose | Notes | -|-------|--------|---------|-------| -| `advisory:ingest` / `vex:ingest` | Concelier / Excititor collectors | Append raw documents through ingestion endpoints. | Paired with tenant claims; requests without tenant are rejected. | -| `advisory:read` / `vex:read` | DevOps verify identity, CLI | Run `stella aoc verify` or call `/aoc/verify`. | Read-only; cannot mutate raw docs. | -| `effective:write` | Policy Engine | Materialise `effective_finding_*` overlays. | Only Policy Engine identity may hold; ingestion contexts receive `ERR_AOC_006` if they attempt. | -| `findings:read` | Console, CLI, exports | Consume derived findings. | Enforced by Gateway and downstream services. | - ---- - -## 3 · Data & control flow highlights - -1. **Ingestion:** Concelier / Excititor connectors fetch upstream documents, compute linksets, and hand payloads to `AOCWriteGuard`. Guards validate schema, provenance, forbidden fields, supersedes pointers, and append-only rules before writing to Mongo. -2. **Verification:** `stella aoc verify` (CLI/CI) and `/aoc/verify` endpoints replay guard checks against stored documents, mapping `ERR_AOC_00x` codes to exit codes for automation. -3. **Policy evaluation:** Mongo change streams deliver tenant-scoped raw deltas. Policy Engine joins SBOM inventory (via BOM Index), executes deterministic policies, writes overlays, and emits events to Scheduler/Notify. -4. **Experience surfaces:** Console renders an AOC dashboard showing ingestion latency, guard violations, and supersedes depth. CLI exposes raw-document fetch helpers for auditing. Offline Kit bundles raw collections alongside guard configs to keep air-gapped installs verifiable. -5. **Observability:** All services emit `ingestion_write_total`, `aoc_violation_total{code}`, `ingestion_latency_seconds`, and trace spans `ingest.fetch`, `ingest.transform`, `ingest.write`, `aoc.guard`. Logs correlate via `traceId`, `tenant`, `source.vendor`, and `content_hash`. - ---- - -## 4 · Offline & disaster readiness - -- **Offline Kit:** Packages raw Mongo snapshots (`advisory_raw`, `vex_raw`) plus guard configuration and CLI verifier binaries so air-gapped sites can re-run AOC checks before promotion. -- **Recovery:** Supersedes chains allow rollback to prior revisions without mutating documents. Disaster exercises must rehearse restoring from snapshot, replaying change streams into Policy Engine, and re-validating guard compliance. -- **Migration:** Legacy normalised fields are moved to temporary views during cutover; ingestion runtime removes writes once guard-enforced path is live (see [Migration playbook](../ingestion/aggregation-only-contract.md#8-migration-playbook)). - ---- - -## 5 · References - -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) -- [Concelier architecture](../ARCHITECTURE_CONCELIER.md) -- [Excititor architecture](../ARCHITECTURE_EXCITITOR.md) -- [Policy Engine architecture](policy-engine.md) -- [Authority service](../ARCHITECTURE_AUTHORITY.md) -- [Observability standards (upcoming)](../observability/policy.md) – interim reference for telemetry naming. - ---- - -## 6 · Compliance checklist - -- [ ] AOC guard enabled for all Concelier and Excititor write paths in production. -- [ ] Mongo schema validators deployed for `advisory_raw` and `vex_raw`; change streams scoped per tenant. -- [ ] Authority scopes (`advisory:*`, `vex:*`, `effective:*`) configured in Gateway and validated via integration tests. -- [ ] `stella aoc verify` wired into CI/CD pipelines with seeded violation fixtures. -- [ ] Console AOC dashboard and CLI documentation reference the new ingestion contract. -- [ ] Offline Kit bundles include guard configs, verifier tooling, and documentation updates. -- [ ] Observability dashboards include violation, latency, and supersedes depth metrics with alert thresholds. - ---- - -*Last updated: 2025-10-26 (Sprint 19).* +# StellaOps Architecture Overview (Sprint 19) + +> **Ownership:** Architecture Guild • Docs Guild +> **Audience:** Service owners, platform engineers, solution architects +> **Related:** [High-Level Architecture](../../07_HIGH_LEVEL_ARCHITECTURE.md), [Concelier Architecture](../concelier/architecture.md), [Policy Engine Architecture](../policy/architecture.md), [Aggregation-Only Contract](../../ingestion/aggregation-only-contract.md) + +This dossier summarises the end-to-end runtime topology after the Aggregation-Only Contract (AOC) rollout. It highlights where raw facts live, how ingest services enforce guardrails, and how downstream components consume those facts to derive policy decisions and user-facing experiences. + +--- + +## 1 · System landscape + +```mermaid +graph TD + subgraph Edge["Clients & Automation"] + CLI[stella CLI] + UI[Console SPA] + APIClients[CI / API Clients] + end + Gateway[API Gateway
(JWT + DPoP scopes)] + subgraph Scanner["Fact Collection"] + ScannerWeb[Scanner.WebService] + ScannerWorkers[Scanner.Workers] + Agent[Agent Runtime] + end + subgraph Ingestion["Aggregation-Only Ingestion (AOC)"] + Concelier[Concelier.WebService] + Excititor[Excititor.WebService] + RawStore[(MongoDB
advisory_raw / vex_raw)] + end + subgraph Derivation["Policy & Overlay"] + Policy[Policy Engine] + Scheduler[Scheduler Services] + Notify[Notifier] + end + subgraph Experience["UX & Export"] + UIService[Console Backend] + Exporters[Export / Offline Kit] + end + Observability[Telemetry Stack] + + CLI --> Gateway + UI --> Gateway + APIClients --> Gateway + Gateway --> ScannerWeb + ScannerWeb --> ScannerWorkers + ScannerWorkers --> Concelier + ScannerWorkers --> Excititor + Concelier --> RawStore + Excititor --> RawStore + RawStore --> Policy + Policy --> Scheduler + Policy --> Notify + Policy --> UIService + Scheduler --> UIService + UIService --> Exporters + Exporters --> CLI + Exporters --> Offline[Offline Kit] + Observability -.-> ScannerWeb + Observability -.-> Concelier + Observability -.-> Excititor + Observability -.-> Policy + Observability -.-> Scheduler + Observability -.-> Notify +``` + +Key boundaries: + +- **AOC border.** Everything inside the Ingestion subgraph writes only immutable raw facts plus link hints. Derived severity, consensus, and risk remain outside the border. +- **Policy-only derivation.** Policy Engine materialises `effective_finding_*` collections and emits overlays; other services consume but never mutate them. +- **Tenant enforcement.** Authority-issued DPoP scopes flow through Gateway to every service; raw stores and overlays include `tenant` strictly. + +--- + +## 2 · Aggregation-Only Contract focus + +### 2.1 Responsibilities at the boundary + +| Area | Services | Responsibilities under AOC | Forbidden under AOC | +|------|----------|-----------------------------|---------------------| +| **Ingestion (Concelier / Excititor)** | `StellaOps.Concelier.WebService`, `StellaOps.Excititor.WebService` | Fetch upstream advisories/VEX, verify signatures, compute linksets, append immutable documents to `advisory_raw` / `vex_raw`, emit observability signals, expose raw read APIs. | Computing severity, consensus, suppressions, or policy hints; merging upstream sources into a single derived record; mutating existing documents. | +| **Policy & Overlay** | `StellaOps.Policy.Engine`, Scheduler | Join SBOM inventory with raw advisories/VEX, evaluate policies, issue `effective_finding_*` overlays, drive remediation workflows. | Writing to raw collections; bypassing guard scopes; running without recorded provenance. | +| **Experience layers** | Console, CLI, Exporters | Surface raw facts + policy overlays; run `stella aoc verify`; render AOC dashboards and reports. | Accepting ingestion payloads that lack provenance or violate guard results. | + +### 2.2 Raw stores + +| Collection | Purpose | Key fields | Notes | +|------------|---------|------------|-------| +| `advisory_raw` | Immutable vendor/ecosystem advisory documents. | `_id`, `tenant`, `source.*`, `upstream.*`, `content.raw`, `linkset`, `supersedes`. | Idempotent by `(source.vendor, upstream.upstream_id, upstream.content_hash)`. | +| `vex_raw` | Immutable vendor VEX statements. | Mirrors `advisory_raw`; `identifiers.statements` summarises affected components. | Maintains supersedes chain identical to advisory flow. | +| Change streams (`advisory_raw_stream`, `vex_raw_stream`) | Feed Policy Engine and Scheduler. | `operationType`, `documentKey`, `fullDocument`, `tenant`, `traceId`. | Scope filtered per tenant before delivery. | + +### 2.3 Guarded ingestion sequence + +```mermaid +sequenceDiagram + participant Upstream as Upstream Source + participant Connector as Concelier/Excititor Connector + participant Guard as AOCWriteGuard + participant Mongo as MongoDB (advisory_raw / vex_raw) + participant Stream as Change Stream + participant Policy as Policy Engine + + Upstream-->>Connector: CSAF / OSV / VEX document + Connector->>Connector: Normalize transport, compute content_hash + Connector->>Guard: Candidate raw doc (source + upstream + content + linkset) + Guard-->>Connector: ERR_AOC_00x on violation + Guard->>Mongo: Append immutable document (with tenant & supersedes) + Mongo-->>Stream: Change event (tenant scoped) + Stream->>Policy: Raw delta payload + Policy->>Policy: Evaluate policies, compute effective findings +``` + +--- + +### 2.4 Authority scopes & tenancy + +| Scope | Holder | Purpose | Notes | +|-------|--------|---------|-------| +| `advisory:ingest` / `vex:ingest` | Concelier / Excititor collectors | Append raw documents through ingestion endpoints. | Paired with tenant claims; requests without tenant are rejected. | +| `advisory:read` / `vex:read` | DevOps verify identity, CLI | Run `stella aoc verify` or call `/aoc/verify`. | Read-only; cannot mutate raw docs. | +| `effective:write` | Policy Engine | Materialise `effective_finding_*` overlays. | Only Policy Engine identity may hold; ingestion contexts receive `ERR_AOC_006` if they attempt. | +| `findings:read` | Console, CLI, exports | Consume derived findings. | Enforced by Gateway and downstream services. | + +--- + +## 3 · Data & control flow highlights + +1. **Ingestion:** Concelier / Excititor connectors fetch upstream documents, compute linksets, and hand payloads to `AOCWriteGuard`. Guards validate schema, provenance, forbidden fields, supersedes pointers, and append-only rules before writing to Mongo. +2. **Verification:** `stella aoc verify` (CLI/CI) and `/aoc/verify` endpoints replay guard checks against stored documents, mapping `ERR_AOC_00x` codes to exit codes for automation. +3. **Policy evaluation:** Mongo change streams deliver tenant-scoped raw deltas. Policy Engine joins SBOM inventory (via BOM Index), executes deterministic policies, writes overlays, and emits events to Scheduler/Notify. +4. **Experience surfaces:** Console renders an AOC dashboard showing ingestion latency, guard violations, and supersedes depth. CLI exposes raw-document fetch helpers for auditing. Offline Kit bundles raw collections alongside guard configs to keep air-gapped installs verifiable. +5. **Observability:** All services emit `ingestion_write_total`, `aoc_violation_total{code}`, `ingestion_latency_seconds`, and trace spans `ingest.fetch`, `ingest.transform`, `ingest.write`, `aoc.guard`. Logs correlate via `traceId`, `tenant`, `source.vendor`, and `content_hash`. + +--- + +## 4 · Offline & disaster readiness + +- **Offline Kit:** Packages raw Mongo snapshots (`advisory_raw`, `vex_raw`) plus guard configuration and CLI verifier binaries so air-gapped sites can re-run AOC checks before promotion. +- **Recovery:** Supersedes chains allow rollback to prior revisions without mutating documents. Disaster exercises must rehearse restoring from snapshot, replaying change streams into Policy Engine, and re-validating guard compliance. +- **Migration:** Legacy normalised fields are moved to temporary views during cutover; ingestion runtime removes writes once guard-enforced path is live (see [Migration playbook](../../ingestion/aggregation-only-contract.md#8-migration-playbook)). + +--- + +## 5 · References + +- [Aggregation-Only Contract reference](../../ingestion/aggregation-only-contract.md) +- [Concelier architecture](../concelier/architecture.md) +- [Excititor architecture](../excititor/architecture.md) +- [Policy Engine architecture](policy-engine.md) +- [Authority service](../authority/architecture.md) +- [Observability standards (upcoming)](../../observability/policy.md) – interim reference for telemetry naming. + +--- + +## 6 · Compliance checklist + +- [ ] AOC guard enabled for all Concelier and Excititor write paths in production. +- [ ] Mongo schema validators deployed for `advisory_raw` and `vex_raw`; change streams scoped per tenant. +- [ ] Authority scopes (`advisory:*`, `vex:*`, `effective:*`) configured in Gateway and validated via integration tests. +- [ ] `stella aoc verify` wired into CI/CD pipelines with seeded violation fixtures. +- [ ] Console AOC dashboard and CLI documentation reference the new ingestion contract. +- [ ] Offline Kit bundles include guard configs, verifier tooling, and documentation updates. +- [ ] Observability dashboards include violation, latency, and supersedes depth metrics with alert thresholds. + +--- + +*Last updated: 2025-10-26 (Sprint 19).* diff --git a/docs/modules/platform/architecture.md b/docs/modules/platform/architecture.md new file mode 100644 index 00000000..a794ff6b --- /dev/null +++ b/docs/modules/platform/architecture.md @@ -0,0 +1,7 @@ +# Platform architecture + +> Cross-cutting view anchored in the Authority, Policy, Graph, Vulnerability Explorer, Orchestrator, Export Center, and Notifications module documentation set. + +This placeholder summarises the planned architecture for Platform. Consolidate design details from implementation plans and upcoming epics before coding. + +Refer to the module README and implementation plan for immediate context, and update this document once component boundaries and data flows are finalised. diff --git a/docs/modules/platform/implementation_plan.md b/docs/modules/platform/implementation_plan.md new file mode 100644 index 00000000..2ced0748 --- /dev/null +++ b/docs/modules/platform/implementation_plan.md @@ -0,0 +1,22 @@ +# Implementation plan — Platform + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 1 – AOC enforcement:** maintain authoritative guardrail docs, schemas, and verifier checklists. +- **Epics 2 & 4 – Policy Engine/Studio:** coordinate platform-wide governance, approvals, and tenancy scopes. +- **Epic 5 – SBOM Graph Explorer:** define shared contracts for graph indexing and overlays. +- **Epics 6–11:** ensure cross-cutting contracts (Explorer, Lens, AI, Orchestrator, Notifications) stay aligned. +- Track additional platform updates in ../../TASKS.md and docs/implplan/SPRINTS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/modules/policy/AGENTS.md b/docs/modules/policy/AGENTS.md new file mode 100644 index 00000000..cbddc17a --- /dev/null +++ b/docs/modules/policy/AGENTS.md @@ -0,0 +1,22 @@ +# Policy Engine agent guide + +## Mission +Policy Engine compiles and evaluates Stella DSL policies deterministically, producing explainable findings with full provenance. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/policy/README.md b/docs/modules/policy/README.md new file mode 100644 index 00000000..54cd0ab5 --- /dev/null +++ b/docs/modules/policy/README.md @@ -0,0 +1,31 @@ +# StellaOps Policy Engine + +Policy Engine compiles and evaluates Stella DSL policies deterministically, producing explainable findings with full provenance. + +## Responsibilities +- Compile `stella-dsl@1` packs into executable graphs. +- Join advisories, VEX evidence, and SBOM inventories to derive effective findings. +- Expose simulation and diff APIs for UI/CLI workflows. +- Emit change-stream driven events for Notify/Scheduler integrations. + +## Key components +- `StellaOps.Policy.Engine` service host. +- Shared libraries under `StellaOps.Policy.*` for evaluation, storage, DSL tooling. + +## Integrations & dependencies +- MongoDB findings collections, RustFS explain bundles. +- Scheduler for incremental re-evaluation triggers. +- CLI/UI for policy authoring and runs. + +## Operational notes +- DSL grammar and lifecycle docs in ../../policy/. +- Observability guidance in ../../observability/policy.md. +- Governance and scope mapping in ../../security/policy-governance.md. + +## Backlog references +- DOCS-POLICY-20-001 … DOCS-POLICY-20-012 (completed baseline). +- DOCS-POLICY-23-007 (upcoming command updates). + +## Epic alignment +- **Epic 2 – Policy Engine & Editor:** deliver deterministic evaluation, DSL infrastructure, explain traces, and incremental runs. +- **Epic 4 – Policy Studio:** integrate registry workflows, simulation at scale, approvals, and promotion semantics. diff --git a/docs/modules/policy/TASKS.md b/docs/modules/policy/TASKS.md new file mode 100644 index 00000000..99164b00 --- /dev/null +++ b/docs/modules/policy/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Policy Engine + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| POLICY ENGINE-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| POLICY ENGINE-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| POLICY ENGINE-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/architecture/policy-engine.md b/docs/modules/policy/architecture.md similarity index 96% rename from docs/architecture/policy-engine.md rename to docs/modules/policy/architecture.md index fffc61ae..f91470f9 100644 --- a/docs/architecture/policy-engine.md +++ b/docs/modules/policy/architecture.md @@ -1,243 +1,245 @@ -# Policy Engine Architecture (v2) - -> **Ownership:** Policy Guild • Platform Guild -> **Services:** `StellaOps.Policy.Engine` (Minimal API + worker host) -> **Data Stores:** MongoDB (`policies`, `policy_runs`, `effective_finding_*`), Object storage (explain bundles), optional NATS/Mongo queue -> **Related docs:** [Policy overview](../policy/overview.md), [DSL](../policy/dsl.md), [Lifecycle](../policy/lifecycle.md), [Runs](../policy/runs.md), [REST API](../api/policy.md), [Policy CLI](../cli/policy.md), [Architecture overview](../architecture/overview.md), [AOC reference](../ingestion/aggregation-only-contract.md) - -This dossier describes the internal structure of the Policy Engine service delivered in Epic 2. It focuses on module boundaries, deterministic evaluation, orchestration, and integration contracts with Concelier, Excititor, SBOM Service, Authority, Scheduler, and Observability stacks. - -The service operates strictly downstream of the **Aggregation-Only Contract (AOC)**. It consumes immutable `advisory_raw` and `vex_raw` documents emitted by Concelier and Excititor, derives findings inside Policy-owned collections, and never mutates ingestion stores. Refer to the architecture overview and AOC reference for system-wide guardrails and provenance obligations. - ---- - -## 1 · Responsibilities & Constraints - -- Compile and evaluate `stella-dsl@1` policy packs into deterministic verdicts. -- Join SBOM inventory, Concelier advisories, and Excititor VEX evidence via canonical linksets and equivalence tables. -- Materialise effective findings (`effective_finding_{policyId}`) with append-only history and produce explain traces. -- Operate incrementally: react to change streams (advisory/vex/SBOM deltas) with ≤ 5 min SLA. -- Provide simulations with diff summaries for UI/CLI workflows without modifying state. -- Enforce strict determinism guard (no wall-clock, RNG, network beyond allow-listed services) and RBAC + tenancy via Authority scopes. -- Support sealed/air-gapped deployments with offline bundles and sealed-mode hints. - -Non-goals: policy authoring UI (handled by Console), ingestion or advisory normalisation (Concelier), VEX consensus (Excititor), runtime enforcement (Zastava). - ---- - -## 2 · High-Level Architecture - -```mermaid -graph TD - subgraph Clients - CLI[stella CLI] - UI[Console Policy Editor] - CI[CI Pipelines] - end - subgraph PolicyEngine["StellaOps.Policy.Engine"] - API[Minimal API Host] - Orchestrator[Run Orchestrator] - WorkerPool[Evaluation Workers] - Compiler[DSL Compiler Cache] - Materializer[Effective Findings Writer] - end - subgraph RawStores["Raw Stores (AOC)"] - AdvisoryRaw[(MongoDB
advisory_raw)] - VexRaw[(MongoDB
vex_raw)] - end - subgraph Derived["Derived Stores"] - Mongo[(MongoDB
policies / policy_runs / effective_finding_*)] - Blob[(Object Store / Evidence Locker)] - Queue[(Mongo Queue / NATS)] - end - Concelier[(Concelier APIs)] - Excititor[(Excititor APIs)] - SBOM[(SBOM Service)] - Authority[(Authority / DPoP Gateway)] - - CLI --> API - UI --> API - CI --> API - API --> Compiler - API --> Orchestrator - Orchestrator --> Queue - Queue --> WorkerPool - Concelier --> AdvisoryRaw - Excititor --> VexRaw - WorkerPool --> AdvisoryRaw - WorkerPool --> VexRaw - WorkerPool --> SBOM - WorkerPool --> Materializer - Materializer --> Mongo - WorkerPool --> Blob - API --> Mongo - API --> Blob - API --> Authority - Orchestrator --> Mongo - Authority --> API -``` - -Key notes: - -- API host exposes lifecycle, run, simulate, findings endpoints with DPoP-bound OAuth enforcement. -- Orchestrator manages run scheduling/fairness; writes run tickets to queue, leases jobs to worker pool. -- Workers evaluate policies using cached IR; join external services via tenant-scoped clients; pull immutable advisories/VEX from the raw stores; write derived overlays to Mongo and optional explain bundles to blob storage. -- Observability (metrics/traces/logs) integrated via OpenTelemetry (not shown). - ---- - -### 2.1 · AOC inputs & immutability - -- **Raw-only reads.** Evaluation workers access `advisory_raw` / `vex_raw` via tenant-scoped Mongo clients or the Concelier/Excititor raw APIs. No Policy Engine component is permitted to mutate these collections. -- **Guarded ingestion.** `AOCWriteGuard` rejects forbidden fields before data reaches the raw stores. Policy tests replay known `ERR_AOC_00x` violations to confirm ingestion compliance. -- **Change streams as contract.** Run orchestration stores resumable cursors for raw change streams. Replays of these cursors (e.g., after failover) must yield identical materialisation outcomes. -- **Derived stores only.** All severity, consensus, and suppression state lives in `effective_finding_*` collections and explain bundles owned by Policy Engine. Provenance fields link back to raw document IDs so auditors can trace every verdict. -- **Authority scopes.** Only the Policy Engine service identity holds `effective:write`. Ingestion identities retain `advisory:*`/`vex:*` scopes, ensuring separation of duties enforced by Authority and the API Gateway. - ---- - -## 3 · Module Breakdown - -| Module | Responsibility | Notes | -|--------|----------------|-------| -| **Configuration** (`Configuration/`) | Bind settings (Mongo URIs, queue options, service URLs, sealed mode), validate on start. | Strict schema; fails fast on missing secrets. | -| **Authority Client** (`Authority/`) | Acquire tokens, enforce scopes, perform DPoP key rotation. | Only service identity uses `effective:write`. | -| **DSL Compiler** (`Dsl/`) | Parse, canonicalise, IR generation, checksum caching. | Uses Roslyn-like pipeline; caches by `policyId+version+hash`. | -| **Selection Layer** (`Selection/`) | Batch SBOM ↔ advisory ↔ VEX joiners; apply equivalence tables; support incremental cursors. | Deterministic ordering (SBOM → advisory → VEX). | -| **Evaluator** (`Evaluation/`) | Execute IR with first-match semantics, compute severity/trust/reachability weights, record rule hits. | Stateless; all inputs provided by selection layer. | -| **Materialiser** (`Materialization/`) | Upsert effective findings, append history, manage explain bundle exports. | Mongo transactions per SBOM chunk. | -| **Orchestrator** (`Runs/`) | Change-stream ingestion, fairness, retry/backoff, queue writer. | Works with Scheduler Models DTOs. | -| **API** (`Api/`) | Minimal API endpoints, DTO validation, problem responses, idempotency. | Generated clients for CLI/UI. | -| **Observability** (`Telemetry/`) | Metrics (`policy_run_seconds`, `rules_fired_total`), traces, structured logs. | Sampled rule-hit logs with redaction. | -| **Offline Adapter** (`Offline/`) | Bundle export/import (policies, simulations, runs), sealed-mode enforcement. | Uses DSSE signing via Signer service. | - ---- - -## 4 · Data Model & Persistence - -### 4.1 Collections - -- `policies` – policy versions, metadata, lifecycle states, simulation artefact references. -- `policy_runs` – run records, inputs (cursors, env), stats, determinism hash, run status. -- `policy_run_events` – append-only log (queued, leased, completed, failed, canceled, replay). -- `effective_finding_{policyId}` – current verdict snapshot per finding. -- `effective_finding_{policyId}_history` – append-only history (previous verdicts, timestamps, runId). -- `policy_reviews` – review comments/decisions. - -### 4.2 Schema Highlights - -- Run records include `changeDigests` (hash of advisory/VEX inputs) for replay verification. -- Effective findings store provenance references (`advisory_raw_ids`, `vex_raw_ids`, `sbom_component_id`). -- All collections include `tenant`, `policyId`, `version`, `createdAt`, `updatedAt`, `traceId` for audit. - -### 4.3 Indexing - -- Compound indexes: `{tenant, policyId, status}` on `policies`; `{tenant, policyId, status, startedAt}` on `policy_runs`; `{policyId, sbomId, findingKey}` on findings. -- TTL indexes on transient explain bundle references (configurable). - ---- - -## 5 · Evaluation Pipeline - -```mermaid -sequenceDiagram - autonumber - participant Worker as EvaluationWorker - participant Compiler as CompilerCache - participant Selector as SelectionLayer - participant Eval as Evaluator - participant Mat as Materialiser - participant Expl as ExplainStore - - Worker->>Compiler: Load IR (policyId, version, digest) - Compiler-->>Worker: CompiledPolicy (cached or compiled) - Worker->>Selector: Fetch tuple batches (sbom, advisory, vex) - Selector-->>Worker: Deterministic batches (1024 tuples) - loop For each batch - Worker->>Eval: Execute rules (batch, env) - Eval-->>Worker: Verdicts + rule hits - Worker->>Mat: Upsert effective findings - Mat-->>Worker: Success - Worker->>Expl: Persist sampled explain traces (optional) - end - Worker->>Mat: Append history + run stats - Worker-->>Worker: Compute determinism hash - Worker->>+Mat: Finalize transaction - Mat-->>Worker: Ack -``` - -Determinism guard instrumentation wraps the evaluator, rejecting access to forbidden APIs and ensuring batch ordering remains stable. - ---- - -## 6 · Run Orchestration & Incremental Flow - -- **Change streams:** Concelier and Excititor publish document changes to the scheduler queue (`policy.trigger.delta`). Payload includes `tenant`, `source`, `linkset digests`, `cursor`. -- **Orchestrator:** Maintains per-tenant backlog; merges deltas until time/size thresholds met, then enqueues `PolicyRunRequest`. -- **Queue:** Mongo queue with lease; each job assigned `leaseDuration`, `maxAttempts`. -- **Workers:** Lease jobs, execute evaluation pipeline, report status (success/failure/canceled). Failures with recoverable errors requeue with backoff; determinism or schema violations mark job `failed` and raise incident event. -- **Fairness:** Round-robin per `{tenant, policyId}`; emergency jobs (`priority=emergency`) jump queue but limited via circuit breaker. -- **Replay:** On demand, orchestrator rehydrates run via stored cursors and exports sealed bundle for audit/CI determinism checks. - ---- - -## 7 · Security & Tenancy - -- **Auth:** All API calls pass through Authority gateway; DPoP tokens enforced for service-to-service (Policy Engine service principal). CLI/UI tokens include scope claims. -- **Scopes:** Mutations require `policy:*` scopes corresponding to action; `effective:write` restricted to service identity. -- **Tenancy:** All queries filter by `tenant`. Service identity uses `tenant-global` for shared policies; cross-tenant reads prohibited unless `policy:tenant-admin` scope present. -- **Secrets:** Configuration loaded via environment variables or sealed secrets; runtime avoids writing secrets to logs. -- **Determinism guard:** Static analyzer prevents referencing forbidden namespaces; runtime guard intercepts `DateTime.Now`, `Random`, `Guid`, HTTP clients beyond allow-list. -- **Sealed mode:** Global flag disables outbound network except allow-listed internal hosts; watchers fail fast if unexpected egress attempted. - ---- - -## 8 · Observability - -- Metrics: - - `policy_run_seconds{mode,tenant,policy}` (histogram) - - `policy_run_queue_depth{tenant}` - - `policy_rules_fired_total{policy,rule}` - - `policy_vex_overrides_total{policy,vendor}` -- Logs: Structured JSON with `traceId`, `policyId`, `version`, `runId`, `tenant`, `phase`. Guard ensures no sensitive data leakage. -- Traces: Spans `policy.select`, `policy.evaluate`, `policy.materialize`, `policy.simulate`. Trace IDs surfaced to CLI/UI. -- Incident mode toggles 100 % sampling and extended retention windows. - ---- - -## 9 · Offline / Bundle Integration - -- **Imports:** Offline Kit delivers policy packs, advisory/VEX snapshots, SBOM updates. Policy Engine ingests bundles via `offline import`. -- **Exports:** `stella policy bundle export` packages policy, IR digest, simulations, run metadata; UI provides export triggers. -- **Sealed hints:** Explain traces annotate when cached values used (EPSS, KEV). Run records mark `env.sealed=true`. -- **Sync cadence:** Operators perform monthly bundle sync; Policy Engine warns when snapshots > configured staleness (default 14 days). - ---- - -## 10 · Testing & Quality - -- **Unit tests:** DSL parsing, evaluator semantics, guard enforcement. -- **Integration tests:** Joiners with sample SBOM/advisory/VEX data; materialisation with deterministic ordering; API contract tests generated from OpenAPI. -- **Property tests:** Ensure rule evaluation deterministic across permutations. -- **Golden tests:** Replay recorded runs, compare determinism hash. -- **Performance tests:** Evaluate 100k component / 1M advisory dataset under warmed caches (<30 s full run). -- **Chaos hooks:** Optional toggles to simulate upstream latency/failures; used in staging. - ---- - -## 11 · Compliance Checklist - -- [ ] **Determinism guard enforced:** Static analyzer + runtime guard block wall-clock, RNG, unauthorized network calls. -- [ ] **Incremental correctness:** Change-stream cursors stored and replayed during tests; unit/integration coverage for dedupe. -- [ ] **RBAC validated:** Endpoint scope requirements match Authority configuration; integration tests cover deny/allow. -- [ ] **AOC separation enforced:** No code path writes to `advisory_raw` / `vex_raw`; integration tests capture `ERR_AOC_00x` handling; read-only clients verified. -- [ ] **Effective findings ownership:** Only Policy Engine identity holds `effective:write`; unauthorized callers receive `ERR_AOC_006`. -- [ ] **Observability wired:** Metrics/traces/logs exported with correlation IDs; dashboards include `aoc_violation_total` and ingest latency panels. -- [ ] **Offline parity:** Sealed-mode tests executed; bundle import/export flows documented and validated. -- [ ] **Schema docs synced:** DTOs match Scheduler Models (`SCHED-MODELS-20-001`); JSON schemas committed. -- [ ] **Security reviews complete:** Threat model (including queue poisoning, determinism bypass, data exfiltration) documented; mitigations in place. -- [ ] **Disaster recovery rehearsed:** Run replay+rollback procedures tested and recorded. - ---- - -*Last updated: 2025-10-26 (Sprint 19).* +# Policy Engine Architecture (v2) + +> Derived from Epic 2 – Policy Engine & Policy Editor and Epic 4 – Policy Studio. + +> **Ownership:** Policy Guild • Platform Guild +> **Services:** `StellaOps.Policy.Engine` (Minimal API + worker host) +> **Data Stores:** MongoDB (`policies`, `policy_runs`, `effective_finding_*`), Object storage (explain bundles), optional NATS/Mongo queue +> **Related docs:** [Policy overview](../../policy/overview.md), [DSL](../../policy/dsl.md), [Lifecycle](../../policy/lifecycle.md), [Runs](../../policy/runs.md), [REST API](../../api/policy.md), [Policy CLI](../cli/guides/policy.md), [Architecture overview](../platform/architecture-overview.md), [AOC reference](../../ingestion/aggregation-only-contract.md) + +This dossier describes the internal structure of the Policy Engine service delivered in Epic 2. It focuses on module boundaries, deterministic evaluation, orchestration, and integration contracts with Concelier, Excititor, SBOM Service, Authority, Scheduler, and Observability stacks. + +The service operates strictly downstream of the **Aggregation-Only Contract (AOC)**. It consumes immutable `advisory_raw` and `vex_raw` documents emitted by Concelier and Excititor, derives findings inside Policy-owned collections, and never mutates ingestion stores. Refer to the architecture overview and AOC reference for system-wide guardrails and provenance obligations. + +--- + +## 1 · Responsibilities & Constraints + +- Compile and evaluate `stella-dsl@1` policy packs into deterministic verdicts. +- Join SBOM inventory, Concelier advisories, and Excititor VEX evidence via canonical linksets and equivalence tables. +- Materialise effective findings (`effective_finding_{policyId}`) with append-only history and produce explain traces. +- Operate incrementally: react to change streams (advisory/vex/SBOM deltas) with ≤ 5 min SLA. +- Provide simulations with diff summaries for UI/CLI workflows without modifying state. +- Enforce strict determinism guard (no wall-clock, RNG, network beyond allow-listed services) and RBAC + tenancy via Authority scopes. +- Support sealed/air-gapped deployments with offline bundles and sealed-mode hints. + +Non-goals: policy authoring UI (handled by Console), ingestion or advisory normalisation (Concelier), VEX consensus (Excititor), runtime enforcement (Zastava). + +--- + +## 2 · High-Level Architecture + +```mermaid +graph TD + subgraph Clients + CLI[stella CLI] + UI[Console Policy Editor] + CI[CI Pipelines] + end + subgraph PolicyEngine["StellaOps.Policy.Engine"] + API[Minimal API Host] + Orchestrator[Run Orchestrator] + WorkerPool[Evaluation Workers] + Compiler[DSL Compiler Cache] + Materializer[Effective Findings Writer] + end + subgraph RawStores["Raw Stores (AOC)"] + AdvisoryRaw[(MongoDB
advisory_raw)] + VexRaw[(MongoDB
vex_raw)] + end + subgraph Derived["Derived Stores"] + Mongo[(MongoDB
policies / policy_runs / effective_finding_*)] + Blob[(Object Store / Evidence Locker)] + Queue[(Mongo Queue / NATS)] + end + Concelier[(Concelier APIs)] + Excititor[(Excititor APIs)] + SBOM[(SBOM Service)] + Authority[(Authority / DPoP Gateway)] + + CLI --> API + UI --> API + CI --> API + API --> Compiler + API --> Orchestrator + Orchestrator --> Queue + Queue --> WorkerPool + Concelier --> AdvisoryRaw + Excititor --> VexRaw + WorkerPool --> AdvisoryRaw + WorkerPool --> VexRaw + WorkerPool --> SBOM + WorkerPool --> Materializer + Materializer --> Mongo + WorkerPool --> Blob + API --> Mongo + API --> Blob + API --> Authority + Orchestrator --> Mongo + Authority --> API +``` + +Key notes: + +- API host exposes lifecycle, run, simulate, findings endpoints with DPoP-bound OAuth enforcement. +- Orchestrator manages run scheduling/fairness; writes run tickets to queue, leases jobs to worker pool. +- Workers evaluate policies using cached IR; join external services via tenant-scoped clients; pull immutable advisories/VEX from the raw stores; write derived overlays to Mongo and optional explain bundles to blob storage. +- Observability (metrics/traces/logs) integrated via OpenTelemetry (not shown). + +--- + +### 2.1 · AOC inputs & immutability + +- **Raw-only reads.** Evaluation workers access `advisory_raw` / `vex_raw` via tenant-scoped Mongo clients or the Concelier/Excititor raw APIs. No Policy Engine component is permitted to mutate these collections. +- **Guarded ingestion.** `AOCWriteGuard` rejects forbidden fields before data reaches the raw stores. Policy tests replay known `ERR_AOC_00x` violations to confirm ingestion compliance. +- **Change streams as contract.** Run orchestration stores resumable cursors for raw change streams. Replays of these cursors (e.g., after failover) must yield identical materialisation outcomes. +- **Derived stores only.** All severity, consensus, and suppression state lives in `effective_finding_*` collections and explain bundles owned by Policy Engine. Provenance fields link back to raw document IDs so auditors can trace every verdict. +- **Authority scopes.** Only the Policy Engine service identity holds `effective:write`. Ingestion identities retain `advisory:*`/`vex:*` scopes, ensuring separation of duties enforced by Authority and the API Gateway. + +--- + +## 3 · Module Breakdown + +| Module | Responsibility | Notes | +|--------|----------------|-------| +| **Configuration** (`Configuration/`) | Bind settings (Mongo URIs, queue options, service URLs, sealed mode), validate on start. | Strict schema; fails fast on missing secrets. | +| **Authority Client** (`Authority/`) | Acquire tokens, enforce scopes, perform DPoP key rotation. | Only service identity uses `effective:write`. | +| **DSL Compiler** (`Dsl/`) | Parse, canonicalise, IR generation, checksum caching. | Uses Roslyn-like pipeline; caches by `policyId+version+hash`. | +| **Selection Layer** (`Selection/`) | Batch SBOM ↔ advisory ↔ VEX joiners; apply equivalence tables; support incremental cursors. | Deterministic ordering (SBOM → advisory → VEX). | +| **Evaluator** (`Evaluation/`) | Execute IR with first-match semantics, compute severity/trust/reachability weights, record rule hits. | Stateless; all inputs provided by selection layer. | +| **Materialiser** (`Materialization/`) | Upsert effective findings, append history, manage explain bundle exports. | Mongo transactions per SBOM chunk. | +| **Orchestrator** (`Runs/`) | Change-stream ingestion, fairness, retry/backoff, queue writer. | Works with Scheduler Models DTOs. | +| **API** (`Api/`) | Minimal API endpoints, DTO validation, problem responses, idempotency. | Generated clients for CLI/UI. | +| **Observability** (`Telemetry/`) | Metrics (`policy_run_seconds`, `rules_fired_total`), traces, structured logs. | Sampled rule-hit logs with redaction. | +| **Offline Adapter** (`Offline/`) | Bundle export/import (policies, simulations, runs), sealed-mode enforcement. | Uses DSSE signing via Signer service. | + +--- + +## 4 · Data Model & Persistence + +### 4.1 Collections + +- `policies` – policy versions, metadata, lifecycle states, simulation artefact references. +- `policy_runs` – run records, inputs (cursors, env), stats, determinism hash, run status. +- `policy_run_events` – append-only log (queued, leased, completed, failed, canceled, replay). +- `effective_finding_{policyId}` – current verdict snapshot per finding. +- `effective_finding_{policyId}_history` – append-only history (previous verdicts, timestamps, runId). +- `policy_reviews` – review comments/decisions. + +### 4.2 Schema Highlights + +- Run records include `changeDigests` (hash of advisory/VEX inputs) for replay verification. +- Effective findings store provenance references (`advisory_raw_ids`, `vex_raw_ids`, `sbom_component_id`). +- All collections include `tenant`, `policyId`, `version`, `createdAt`, `updatedAt`, `traceId` for audit. + +### 4.3 Indexing + +- Compound indexes: `{tenant, policyId, status}` on `policies`; `{tenant, policyId, status, startedAt}` on `policy_runs`; `{policyId, sbomId, findingKey}` on findings. +- TTL indexes on transient explain bundle references (configurable). + +--- + +## 5 · Evaluation Pipeline + +```mermaid +sequenceDiagram + autonumber + participant Worker as EvaluationWorker + participant Compiler as CompilerCache + participant Selector as SelectionLayer + participant Eval as Evaluator + participant Mat as Materialiser + participant Expl as ExplainStore + + Worker->>Compiler: Load IR (policyId, version, digest) + Compiler-->>Worker: CompiledPolicy (cached or compiled) + Worker->>Selector: Fetch tuple batches (sbom, advisory, vex) + Selector-->>Worker: Deterministic batches (1024 tuples) + loop For each batch + Worker->>Eval: Execute rules (batch, env) + Eval-->>Worker: Verdicts + rule hits + Worker->>Mat: Upsert effective findings + Mat-->>Worker: Success + Worker->>Expl: Persist sampled explain traces (optional) + end + Worker->>Mat: Append history + run stats + Worker-->>Worker: Compute determinism hash + Worker->>+Mat: Finalize transaction + Mat-->>Worker: Ack +``` + +Determinism guard instrumentation wraps the evaluator, rejecting access to forbidden APIs and ensuring batch ordering remains stable. + +--- + +## 6 · Run Orchestration & Incremental Flow + +- **Change streams:** Concelier and Excititor publish document changes to the scheduler queue (`policy.trigger.delta`). Payload includes `tenant`, `source`, `linkset digests`, `cursor`. +- **Orchestrator:** Maintains per-tenant backlog; merges deltas until time/size thresholds met, then enqueues `PolicyRunRequest`. +- **Queue:** Mongo queue with lease; each job assigned `leaseDuration`, `maxAttempts`. +- **Workers:** Lease jobs, execute evaluation pipeline, report status (success/failure/canceled). Failures with recoverable errors requeue with backoff; determinism or schema violations mark job `failed` and raise incident event. +- **Fairness:** Round-robin per `{tenant, policyId}`; emergency jobs (`priority=emergency`) jump queue but limited via circuit breaker. +- **Replay:** On demand, orchestrator rehydrates run via stored cursors and exports sealed bundle for audit/CI determinism checks. + +--- + +## 7 · Security & Tenancy + +- **Auth:** All API calls pass through Authority gateway; DPoP tokens enforced for service-to-service (Policy Engine service principal). CLI/UI tokens include scope claims. +- **Scopes:** Mutations require `policy:*` scopes corresponding to action; `effective:write` restricted to service identity. +- **Tenancy:** All queries filter by `tenant`. Service identity uses `tenant-global` for shared policies; cross-tenant reads prohibited unless `policy:tenant-admin` scope present. +- **Secrets:** Configuration loaded via environment variables or sealed secrets; runtime avoids writing secrets to logs. +- **Determinism guard:** Static analyzer prevents referencing forbidden namespaces; runtime guard intercepts `DateTime.Now`, `Random`, `Guid`, HTTP clients beyond allow-list. +- **Sealed mode:** Global flag disables outbound network except allow-listed internal hosts; watchers fail fast if unexpected egress attempted. + +--- + +## 8 · Observability + +- Metrics: + - `policy_run_seconds{mode,tenant,policy}` (histogram) + - `policy_run_queue_depth{tenant}` + - `policy_rules_fired_total{policy,rule}` + - `policy_vex_overrides_total{policy,vendor}` +- Logs: Structured JSON with `traceId`, `policyId`, `version`, `runId`, `tenant`, `phase`. Guard ensures no sensitive data leakage. +- Traces: Spans `policy.select`, `policy.evaluate`, `policy.materialize`, `policy.simulate`. Trace IDs surfaced to CLI/UI. +- Incident mode toggles 100 % sampling and extended retention windows. + +--- + +## 9 · Offline / Bundle Integration + +- **Imports:** Offline Kit delivers policy packs, advisory/VEX snapshots, SBOM updates. Policy Engine ingests bundles via `offline import`. +- **Exports:** `stella policy bundle export` packages policy, IR digest, simulations, run metadata; UI provides export triggers. +- **Sealed hints:** Explain traces annotate when cached values used (EPSS, KEV). Run records mark `env.sealed=true`. +- **Sync cadence:** Operators perform monthly bundle sync; Policy Engine warns when snapshots > configured staleness (default 14 days). + +--- + +## 10 · Testing & Quality + +- **Unit tests:** DSL parsing, evaluator semantics, guard enforcement. +- **Integration tests:** Joiners with sample SBOM/advisory/VEX data; materialisation with deterministic ordering; API contract tests generated from OpenAPI. +- **Property tests:** Ensure rule evaluation deterministic across permutations. +- **Golden tests:** Replay recorded runs, compare determinism hash. +- **Performance tests:** Evaluate 100k component / 1M advisory dataset under warmed caches (<30 s full run). +- **Chaos hooks:** Optional toggles to simulate upstream latency/failures; used in staging. + +--- + +## 11 · Compliance Checklist + +- [ ] **Determinism guard enforced:** Static analyzer + runtime guard block wall-clock, RNG, unauthorized network calls. +- [ ] **Incremental correctness:** Change-stream cursors stored and replayed during tests; unit/integration coverage for dedupe. +- [ ] **RBAC validated:** Endpoint scope requirements match Authority configuration; integration tests cover deny/allow. +- [ ] **AOC separation enforced:** No code path writes to `advisory_raw` / `vex_raw`; integration tests capture `ERR_AOC_00x` handling; read-only clients verified. +- [ ] **Effective findings ownership:** Only Policy Engine identity holds `effective:write`; unauthorized callers receive `ERR_AOC_006`. +- [ ] **Observability wired:** Metrics/traces/logs exported with correlation IDs; dashboards include `aoc_violation_total` and ingest latency panels. +- [ ] **Offline parity:** Sealed-mode tests executed; bundle import/export flows documented and validated. +- [ ] **Schema docs synced:** DTOs match Scheduler Models (`SCHED-MODELS-20-001`); JSON schemas committed. +- [ ] **Security reviews complete:** Threat model (including queue poisoning, determinism bypass, data exfiltration) documented; mitigations in place. +- [ ] **Disaster recovery rehearsed:** Run replay+rollback procedures tested and recorded. + +--- + +*Last updated: 2025-10-26 (Sprint 19).* diff --git a/docs/modules/policy/implementation_plan.md b/docs/modules/policy/implementation_plan.md new file mode 100644 index 00000000..58ebbf2f --- /dev/null +++ b/docs/modules/policy/implementation_plan.md @@ -0,0 +1,67 @@ +# Implementation plan — Policy Engine + +## Delivery phases +- **Phase 1 – Deterministic evaluation core** + Finalise DSL compiler, runtime guardrails, evaluation workers, change-stream integration (advisories, VEX, SBOM), and append-only effective findings. +- **Phase 2 – Orchestration & incremental runs** + Implement run scheduler, incremental deltas, change-stream replay, simulation hooks, and determinism hashing. +- **Phase 3 – Policy Studio workflows** + Deliver policy registry, versioning, approvals, explain trace API, client editor integration, and signed promotion pipelines. +- **Phase 4 – Simulation & approvals** + Provide diff/simulation APIs, approval queues, change management, and integration with CLI/Console. +- **Phase 5 – Exports & offline parity** + Produce policy bundles, explain archives, Offline Kit assets, and deterministic manifests; integrate with Export Center. +- **Phase 6 – Observability & hardening** + Ship metrics, logs, traces, incident response runbooks, guardrail analyzers, and compliance attestations. + +## Work breakdown +- **Evaluation engine** + - DSL compiler with caching, static analysis, and guard rails (no wall-clock/random/network outside allowlist). + - Batch evaluator with deterministic ordering, change-stream inputs, policy IR caching. + - Explain trace generation, evidence linking, storage in object store. +- **Run orchestration** + - Scheduler for incremental runs, job leasing, fair-share per tenant/policy. + - Determinism hash + replay verification, time-travel snapshots, resume cursors. + - Simulation endpoints returning diff summaries, rationale breakdown, exit codes. +- **Policy Studio** + - Policy registry (draft→review→approved), signed promotion pipeline, approvals workflow (multi-step). + - Console integration (editor, simulation, approvals, explain viewer) and CLI parity. +- **Integrations** + - Inputs: Concelier, Excititor, SBOM Service, VEX Lens, runtime signals. + - Outputs: Findings ledger, Vuln Explorer, Notify (policy events), Export Center (policy bundles). + - Authority scopes, tenancy enforcement, RBAC for policy author/reviewer/operator. +- **Observability & compliance** + - Metrics: run duration, evaluation verdict counts, simulation latency, guard violations. + - Logs/traces with trace ID propagation, policy version references, tenant scoping. + - Guard analyzers (static + runtime), unit/property tests, compliance reports. +- **Docs & tooling** + - Update DSL guide, policy lifecycle/runbooks, simulation manual, CLI reference, Offline Kit instructions. + - Provide sample policies, fixtures, and analyzer rules. + +## Acceptance criteria +- Evaluation engine deterministic across runs; effective findings materialised only by Policy Engine; guardrails prevent forbidden IO. +- Incremental runs handle advisory/VEX/SBOM deltas within ≤5 min SLA; determinism hash and replay verification succeed. +- Policy Studio supports draft/review/approval, signed promotions, simulation diffing, and explain traces in UI/CLI. +- Exports (policy bundles, explain archives) reproducible with signed manifests; Offline Kit packages deliver same tooling. +- Observability dashboards show run metrics, guard violations, simulation usage; alerts trigger on determinism hash mismatch or backlog. +- CLI/Console parity for policy management, simulation, approvals, and export workflows. + +## Risks & mitigations +- **Non-determinism:** strict static analysis, runtime guard, determinism hash, replay tests. +- **Policy drift vs reality:** simulation diff previews, approval workflow, history/audit trail. +- **Scaling evaluations:** sharded workers, incremental deltas, caching, job queue fairness. +- **Guard bypass:** analyzers integrated into CI, runtime guard rejects forbidden operations. +- **Offline compliance:** deterministic exports, manifest verification, documentation for sealed-mode deployments. + +## Test strategy +- **Unit:** DSL parsing, guard analyzer, evaluation pipeline, simulation diff calculations. +- **Property:** randomised policy inputs verifying determinism and guard enforcement. +- **Integration:** Concelier/Excititor/SBOM feeds → Policy Engine → findings ledger, simulation, approvals. +- **Performance:** evaluation throughput, change-stream backlog recovery, simulation under load. +- **Security/compliance:** RBAC/tenancy, analyzer enforcement, audit logging, signed promotions. +- **Offline:** export/import of policy bundles, explain archives, CLI verification. + +## Definition of done +- Policy Engine core, orchestration, Policy Studio workflows, exports, and observability delivered with runbooks and Offline Kit parity. +- Documentation suite (overview, architecture, DSL, lifecycle, Studio, simulation, CLI) updated with imposed rule statements. +- ./TASKS.md and ../../TASKS.md reflect status; analyzers integrated into CI; compliance evidence captured. diff --git a/docs/modules/registry/AGENTS.md b/docs/modules/registry/AGENTS.md new file mode 100644 index 00000000..4c2e45c9 --- /dev/null +++ b/docs/modules/registry/AGENTS.md @@ -0,0 +1,22 @@ +# Registry Token Service agent guide + +## Mission +The registry module issues scoped pull tokens for mirrored container registries while enforcing plan and licence constraints. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/registry/README.md b/docs/modules/registry/README.md new file mode 100644 index 00000000..35f5f59d --- /dev/null +++ b/docs/modules/registry/README.md @@ -0,0 +1,34 @@ +# StellaOps Registry Token Service + +The registry module issues scoped pull tokens for mirrored container registries while enforcing plan and licence constraints. + +## Responsibilities +- Validate Authority-issued OpToks and tenant scopes before issuance. +- Mint time-bound registry tokens and record issuance ledgers. +- Expose revocation and audit endpoints for security teams. +- Integrate with Offline Kit for deterministic token manifests. + +## Key components +- `StellaOps.Registry.TokenService` minimal API host. +- Mongo-backed issuance ledger. +- Tests under `src/Registry/__Tests`. + +## Integrations & dependencies +- Authority for identity & scope verification. +- Export Center/Offline Kit for distribution. +- DevOps runbooks for deployment and rotation. + +## Operational notes +- Operational guide at ./operations/token-service.md. +- Telemetry dashboards pending (see ../../TASKS.md). + +## Related resources +- ./operations/token-service.md + +## Backlog references +- DEVOPS-REGISTRY items in ../../TASKS.md (future work). +- Registry automation stories tracked in src/Registry/TASKS.md if present. + +## Epic alignment +- **Epic 10 – Export Center:** provide signed, auditable registry token bundles for mirror distribution. +- **Epic 14 – Identity & Tenancy:** enforce tenant-aware scopes, PoE alignment, and revocation policies. diff --git a/docs/modules/registry/TASKS.md b/docs/modules/registry/TASKS.md new file mode 100644 index 00000000..b08a972b --- /dev/null +++ b/docs/modules/registry/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Registry Token Service + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| REGISTRY TOKEN SERVICE-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| REGISTRY TOKEN SERVICE-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| REGISTRY TOKEN SERVICE-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/modules/registry/architecture.md b/docs/modules/registry/architecture.md new file mode 100644 index 00000000..52e89e0c --- /dev/null +++ b/docs/modules/registry/architecture.md @@ -0,0 +1,7 @@ +# Registry Token Service architecture + +> Grounded in the Export Center and Authority module guides, which describe token issuance, provenance, tenant isolation, and offline packaging expectations. + +This placeholder summarises the planned architecture for Registry Token Service. Consolidate design details from implementation plans and upcoming epics before coding. + +Refer to the module README and implementation plan for immediate context, and update this document once component boundaries and data flows are finalised. diff --git a/docs/modules/registry/implementation_plan.md b/docs/modules/registry/implementation_plan.md new file mode 100644 index 00000000..b8c08685 --- /dev/null +++ b/docs/modules/registry/implementation_plan.md @@ -0,0 +1,20 @@ +# Implementation plan — Registry Token Service + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 10 – Export Center:** deliver signed registry token bundles supporting mirror/Offline Kit workflows. +- **Epic 14 – Identity & Tenancy:** integrate tenant-aware scope validation, revocation, and audit trails. +- Track follow-ups in ../../TASKS.md and src/Registry/TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ops/registry-token-service.md b/docs/modules/registry/operations/token-service.md similarity index 100% rename from docs/ops/registry-token-service.md rename to docs/modules/registry/operations/token-service.md diff --git a/docs/modules/scanner/AGENTS.md b/docs/modules/scanner/AGENTS.md new file mode 100644 index 00000000..92e582cf --- /dev/null +++ b/docs/modules/scanner/AGENTS.md @@ -0,0 +1,22 @@ +# Scanner agent guide + +## Mission +Scanner analyses container images layer-by-layer, producing deterministic SBOM fragments, diffs, and signed reports. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/scanner/README.md b/docs/modules/scanner/README.md new file mode 100644 index 00000000..3acd7f19 --- /dev/null +++ b/docs/modules/scanner/README.md @@ -0,0 +1,38 @@ +# StellaOps Scanner + +Scanner analyses container images layer-by-layer, producing deterministic SBOM fragments, diffs, and signed reports. + +## Responsibilities +- Expose APIs (WebService) for scan orchestration, diffing, and artifact retrieval. +- Run Worker analyzers for OS, language, and native ecosystems with restart-only plug-ins. +- Store SBOM fragments and artifacts in RustFS/object storage. +- Publish DSSE-ready metadata for Signer/Attestor and downstream policy evaluation. + +## Key components +- `StellaOps.Scanner.WebService` minimal API host. +- `StellaOps.Scanner.Worker` analyzer executor. +- Analyzer libraries under `StellaOps.Scanner.Analyzers.*`. + +## Integrations & dependencies +- Scheduler for job intake and retries. +- Policy Engine for evidence handoff. +- Export Center / Offline Kit for artifact packaging. + +## Operational notes +- CAS caches, bounded retries, DSSE integration. +- Monitoring dashboards (see ./operations/analyzers-grafana-dashboard.json). +- RustFS migration playbook. + +## Related resources +- ./operations/analyzers.md +- ./operations/analyzers-grafana-dashboard.json +- ./operations/rustfs-migration.md +- ./operations/entrypoint.md + +## Backlog references +- DOCS-SCANNER updates tracked in ../../TASKS.md. +- Analyzer parity work in src/Scanner/**/TASKS.md. + +## Epic alignment +- **Epic 6 – Vulnerability Explorer:** provide policy-aware scan outputs, explain traces, and findings ledger hooks for triage workflows. +- **Epic 10 – Export Center:** generate export-ready artefacts, manifests, and DSSE metadata for bundles. diff --git a/docs/modules/scanner/TASKS.md b/docs/modules/scanner/TASKS.md new file mode 100644 index 00000000..01f3b800 --- /dev/null +++ b/docs/modules/scanner/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Scanner + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| SCANNER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| SCANNER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| SCANNER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_SCANNER.md b/docs/modules/scanner/architecture.md similarity index 97% rename from docs/ARCHITECTURE_SCANNER.md rename to docs/modules/scanner/architecture.md index 3713850d..042c35da 100644 --- a/docs/ARCHITECTURE_SCANNER.md +++ b/docs/modules/scanner/architecture.md @@ -1,4 +1,6 @@ -# component_architecture_scanner.md — **Stella Ops Scanner** (2025Q4) +# component_architecture_scanner.md — **Stella Ops Scanner** (2025Q4) + +> Aligned with Epic 6 – Vulnerability Explorer and Epic 10 – Export Center. > **Scope.** Implementation‑ready architecture for the **Scanner** subsystem: WebService, Workers, analyzers, SBOM assembly (inventory & usage), per‑layer caching, three‑way diffs, artifact catalog (RustFS default + Mongo, S3-compatible fallback), attestation hand‑off, and scale/security posture. This document is the contract between the scanning plane and everything else (Policy, Excititor, Concelier, UI, CLI). @@ -35,9 +37,9 @@ src/ ├─ StellaOps.Scanner.Diff/ # image→layer→component three‑way diff ├─ StellaOps.Scanner.Index/ # BOM‑Index sidecar (purls + roaring bitmaps) ├─ StellaOps.Scanner.Tests.* # unit/integration/e2e fixtures - └─ tools/ - ├─ StellaOps.Scanner.Sbomer.BuildXPlugin/ # BuildKit generator (image referrer SBOMs) - └─ StellaOps.Scanner.Sbomer.DockerImage/ # CLI‑driven scanner container + └─ Tools/ + ├─ StellaOps.Scanner.Sbomer.BuildXPlugin/ # BuildKit generator (image referrer SBOMs) + └─ StellaOps.Scanner.Sbomer.DockerImage/ # CLI‑driven scanner container ``` Analyzer assemblies and buildx generators are packaged as **restart-time plug-ins** under `plugins/scanner/**` with manifests; services must restart to activate new plug-ins. diff --git a/docs/modules/scanner/implementation_plan.md b/docs/modules/scanner/implementation_plan.md new file mode 100644 index 00000000..a4ea7ef6 --- /dev/null +++ b/docs/modules/scanner/implementation_plan.md @@ -0,0 +1,64 @@ +# Implementation plan — Scanner + +## Delivery phases +- **Phase 1 – Control plane & job queue** + Finalise Scanner WebService, queue abstraction (Redis/NATS), job leasing, CAS layer cache, artifact catalog, and API endpoints. +- **Phase 2 – Analyzer parity & SBOM assembly** + Implement OS/Lang/Native analyzers, inventory/usage SBOM views, entry trace resolution, deterministic component identity. +- **Phase 3 – Diff & attestations** + Deliver three-way diff engine, DSSE SBOM/report signing pipeline, attestation hand-off (Signer→Attestor), metadata for Export Center. +- **Phase 4 – Integrations & exports** + Integrate with Policy Engine, Vuln Explorer, Export Center, CLI/Console; provide buildx plugin, CLI commands, and offline scanning support. +- **Phase 5 – Observability & resilience** + Metrics/logs/traces, queue backpressure handling, cache eviction, runbooks, smoke tests, SLO dashboards. + +## Work breakdown +- **Control plane** + - REST API for scan requests, diff, catalog listing, artifact retrieval. + - Queue service with idempotency, retries, dead-letter handling; worker scaling. + - CAS storage (RustFS + S3 fallback), GC, ILM policies, offline mode. +- **Analyzers** + - OS (apk/dpkg/rpm), language (Java/Node/Python/Go/DotNet/Rust), native (ELF/PE/MachO). + - Deterministic metadata (purl, version, source location), heuristics optional under flags. + - Entry trace/usage analysis, dependency resolution, license detection. +- **SBOM & diff** + - Inventory/usage SBOM assembly, CycloneDX/SPDX emitters, schema validation. + - Three-way diff (base, target, runtime), evidence linking, JSON export. +- **Attestation & export** + - DSSE bundle signing, attestation metadata for Signer/Attestor, provenance summary. + - Export Center integration (SBOM/diff artifacts, manifests), CLI builder plugin (buildx). +- **CLI/Console** + - CLI commands `stella scan`, `stella sbom diff`, `stella sbom export`, offline caching. + - Console flows for scan requests, diff viewer, SBOM downloads, attestation status. +- **Observability & ops** + - Metrics (queue depth, scan latency, cache hit/miss, analyzer timing), logs/traces with job IDs. + - Alerts for backlog, failed scans, attestation issues, storage pressure. + - Runbooks for stuck jobs, cache corruption, analyzer regressions, offline mode. + +## Acceptance criteria +- Scans produce deterministic SBOM inventory/usage views with component identity stability and reproducible diffs. +- Queue/worker pipeline handles retries, backpressure, offline kits, and exports DSSE attestations for Signer/Attestor. +- Export Center consumes SBOM/diff artifacts; Vuln Explorer receives metadata and explain traces. +- CLI/Console parity for scan submission, diffing, exports, attestation verification. +- Observability dashboards cover queue health, analyzer success rates, performance; alerts fire on SLO breaches. +- Offline scanning (air-gapped) supported with local caches and manifest verification. + +## Risks & mitigations +- **Analyzer drift/determinism:** golden fixtures, hash-based regression tests, deterministic sorting, strict identity rules. +- **Queue overload:** adaptive backpressure, scaling workers, dead-letter review, priority lanes. +- **Storage growth:** CAS dedupe, ILM policies, offline bundle pruning. +- **Attestation failures:** retry with backoff, attestation health checks, Notify integration. +- **Offline divergence:** packaging of analyzers/configs, manifest signatures, parity tests. + +## Test strategy +- **Unit:** analyzer parsers, component identity, diff calculations, API validation. +- **Integration:** end-to-end scan/diff/attestation flows, Export Center integration, CLI automation. +- **Performance:** large images, concurrent scans, cache stress, queue throughput. +- **Determinism:** repeated scans/diffs across systems, hash comparisons, property tests. +- **Security:** RBAC, tenant isolation, attestation key handling, path sanitisation. +- **Offline:** air-gap scanning, manifest verification, CLI offline mode. + +## Definition of done +- Scanner services, analyzers, diffing, attestation pipeline, exports, and observability delivered with runbooks and Offline Kit parity. +- Documentation (architecture, analyzer guides, CLI, offline mode, operations) updated with imposed rule statements. +- ./TASKS.md and ../../TASKS.md updated with progress; regression fixtures maintained in repo. diff --git a/docs/ops/scanner-analyzers-grafana-dashboard.json b/docs/modules/scanner/operations/analyzers-grafana-dashboard.json similarity index 100% rename from docs/ops/scanner-analyzers-grafana-dashboard.json rename to docs/modules/scanner/operations/analyzers-grafana-dashboard.json diff --git a/docs/ops/scanner-analyzers-operations.md b/docs/modules/scanner/operations/analyzers.md similarity index 90% rename from docs/ops/scanner-analyzers-operations.md rename to docs/modules/scanner/operations/analyzers.md index c4cf9547..3ec5e195 100644 --- a/docs/ops/scanner-analyzers-operations.md +++ b/docs/modules/scanner/operations/analyzers.md @@ -3,7 +3,7 @@ ## Purpose Keep the language analyzer microbench under the < 5 s SBOM pledge. CI emits Prometheus metrics and JSON fixtures so trend dashboards and alerts stay in lockstep with the repository baseline. -> **Grafana note:** Import `docs/ops/scanner-analyzers-grafana-dashboard.json` into your Prometheus-backed Grafana stack to monitor `scanner_analyzer_bench_*` metrics and alert on regressions. +> **Grafana note:** Import `docs/modules/scanner/operations/analyzers-grafana-dashboard.json` into your Prometheus-backed Grafana stack to monitor `scanner_analyzer_bench_*` metrics and alert on regressions. ## Publishing workflow 1. CI (or engineers running locally) execute: @@ -25,7 +25,7 @@ Keep the language analyzer microbench under the < 5 s SBOM pledge. CI emits - `max_ms` regresses ≥ 20 % versus `baseline.csv`. ## Grafana dashboard -- Import `docs/ops/scanner-analyzers-grafana-dashboard.json`. +- Import `docs/modules/scanner/operations/analyzers-grafana-dashboard.json`. - Point the template variable `datasource` to the Prometheus instance ingesting `scanner_analyzer_bench_*` metrics. - Panels: - **Max Duration (ms)** – compares live runs vs baseline. diff --git a/docs/modules/scanner/operations/entrypoint-dynamic-analysis.md b/docs/modules/scanner/operations/entrypoint-dynamic-analysis.md new file mode 100644 index 00000000..405fe9d0 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-dynamic-analysis.md @@ -0,0 +1,72 @@ +# Entry-Point Dynamic Analysis + +When we have access to a running container (e.g., during runtime posture checks), Stella Ops augments the static inference with live signals. This document describes the Observational Exec Graph (OEG) that powers the dynamic mode. + +## 1) Goals + +- Capture the *actual* process tree and exec lineage after the container starts. +- Identify steady-state processes (long-lived, listening, non-wrapper) even when supervision stacks are present. +- Feed the same reduction and runtime-classification pipeline as the static analyser. + +## 2) Observational Exec Graph (OEG) + +### 2.1 Data sources +- **Tracepoints / eBPF**: `sched_process_exec`, `sched_process_fork/clone`, and corresponding exit events give us pid, ppid, namespace, binary path, and argv snapshots with minimal overhead. +- **/proc sampling**: for each tracked PID, capture `/proc//{exe,cmdline,cwd}` and file descriptors (especially listening sockets). +- **Namespace mapping**: normalise host PIDs to container PIDs (`NStgid`) so the graph is stable across runtimes. + +### 2.2 Graph model + +```csharp +public sealed record ExecNode(int HostPid, int NsPid, int Ppid, string Exe, string[] Argv, long StartTicks); +public sealed record ExecEdge(int ParentHostPid, int ChildHostPid, string Kind); // "clone" | "exec" +``` + +- Nodes represent `exec()` events (post-exec image) and contain the final argv. +- Edges labelled `clone` capture forks; `exec` edges show program replacements. + +### 2.3 Steady-state candidate selection + +For each node compute features: + +| Feature | Rationale | +| --- | --- | +| Lifetime (until sampling end) | Long-lived processes are more likely to be the real workload. | +| Additional execs downstream | Zero execs after start implies terminal. | +| Listening sockets | Owning `LISTEN` sockets strongly suggests a server. | +| Wrapper catalogue hit | Mark nodes that match known shims (`tini`, `gosu`, `supervisord`, etc.). | +| Children fan-out | Supervisors spawn multiple children and remain parents. | + +Feed these into a scoring function; retain Top‑K candidates (usually 1–3) along with evidence. + +## 3) Integration with static pipeline + +1. For each steady-state candidate, snapshot the command/argv and normalise via `ResolvedCommand` (as in static mode). +2. Run wrapper reduction and ShellFlow analysis if the candidate is a script. +3. Invoke runtime detectors to classify the binary. +4. Merge dynamic evidence with static evidence. Conflicts drop confidence or trigger the “supervisor” classification. + +## 4) Supervisors & multi-service containers + +Some images (e.g., `supervisord`, `s6`, `runit`) intentionally start multiple long-lived processes. Handle them as follows: + +- Detect supervisor binaries from the wrapper catalogue. +- Analyse their configuration (`/etc/supervisord.conf`, `/etc/services.d/*`, etc.) to enumerate child services statically. +- Emit multiple `TerminalProcess` entries with individual confidence scores but mark the parent as `type = supervisor`. + +## 5) Operational hints + +- Sampling window: 1–3 seconds after start is usually sufficient; extend in debug mode. +- Overhead: prefer eBPF/tracepoints; fall back to periodic `/proc` walks when instrumentation isn’t available. +- Security: honour namespace boundaries; never inspect processes outside the target container’s cgroup/namespace. +- Failure mode: if dynamic capture fails, fall back to static mode and flag evidence accordingly (`"Dynamic capture unavailable"`). + +## 6) Deliverables + +The dynamic reducer returns an `EntryTraceResult` populated with: + +- `ExecGraph` containing nodes and edges for audit/debug. +- `Terminals` listing steady-state processes (possibly multiple). +- `Evidence` strings referencing dynamic signals (`"pid 47 listening on 0.0.0.0:8080"`, `"wrapper tini collapsed into /usr/local/bin/python"`). + +Downstream modules (Policy, Vuln Explorer, Export Center) treat the result identically to static scans, enabling easy comparison between build-time and runtime observations. diff --git a/docs/modules/scanner/operations/entrypoint-lang-ccpp.md b/docs/modules/scanner/operations/entrypoint-lang-ccpp.md new file mode 100644 index 00000000..e2a7b7fe --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-ccpp.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — C / C++ + +## Signals to gather +- Dynamically linked ELF (`.dynamic`) with GLIBC references (`GLIBC`, `GLIBCXX`, `libstdc++`). +- Presence of `/lib64/ld-linux-*.so.*` loaders. +- Absence of Go/Rust-specific markers. +- Native supervisor binaries (`nginx`, `envoy`, custom C services). +- Config files adjacent to the binary (`/etc/app.conf`, YAML/INI). + +## Implementation notes +- Treat this detector as the "native fallback": confirm no higher-priority language matched. +- Collect shared library list to attach as evidence; highlight unusual dependencies. +- Inspect `EXPOSE` ports and config directories to aid classification. +- Normalise busybox-style symlinks (actual binary often `/bin/busybox` with applet name). + +## Evidence & scoring +- Boost for ELF dynamic dependencies and loader presence. +- Add evidence for config files, service managers, or env variables. +- Penalise extremely small binaries without metadata (may be wrappers). + +## Edge cases +- Static C binaries may look like Go; rely on build ID absence and library fingerprints. +- When binary is part of a supervisor stack (e.g., `s6-svscan`), delegate classification to `Supervisor`. +- Windows native services should be handled by PE analysis (`entrypoint-runtime-overview.md`). diff --git a/docs/modules/scanner/operations/entrypoint-lang-deno.md b/docs/modules/scanner/operations/entrypoint-lang-deno.md new file mode 100644 index 00000000..e7463e1d --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-deno.md @@ -0,0 +1,22 @@ +# Entry-Point Runtime — Deno + +## Signals to gather +- `argv0` equals `deno` or path ends with `/bin/deno`. +- Arguments include `run`, `task`, `serve`, or `compile` outputs. +- Presence of `deno.json` / `deno.jsonc`, `import_map.json`, or cached modules (`/deno-dir`). +- Environment (`DENO_DIR`, `DENO_AUTH_TOKENS`). + +## Implementation notes +- Resolve script URLs or local files; for remote sources record the URL as evidence. +- Distinguish between `deno compile` executables and the Deno runtime invoking a script. +- Recognise `deno task ` by reading tasks from `deno.json`. +- ShellFlow should already collapse Docker official entrypoint (`/usr/bin/env deno task start`). + +## Evidence & scoring +- Boost for confirmed script/URL and config file presence. +- Add evidence for permissions flags (`--allow-net`, `--allow-env`) to aid policy decisions. +- Penalise when only the binary is present without scripts. + +## Edge cases +- Deno deploy shims or adapters may further wrap the runtime; rely on wrapper catalogue. +- When `deno compile` emits a standalone binary, treat it as C/C++ unless metadata persists. diff --git a/docs/modules/scanner/operations/entrypoint-lang-dotnet.md b/docs/modules/scanner/operations/entrypoint-lang-dotnet.md new file mode 100644 index 00000000..5542c5d4 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-dotnet.md @@ -0,0 +1,25 @@ +# Entry-Point Runtime — .NET / C# + +## Signals to gather +- Framework-dependent: `dotnet ` invocation. +- Adjacent `*.runtimeconfig.json` (parse `tfm`, framework references, roll-forward). +- Self-contained or single-file apps: ELF/PE with `DOTNET_BUNDLE`, `System.Private.CoreLib`, or `coreclr` markers. +- ASP.NET hints: `ASPNETCORE_URLS`, `appsettings.json`, presence of `wwwroot`. +- Windows builds: PE with CLI header (managed assembly) or native host embedding a bundle. + +## Implementation notes +- Resolve DLL paths relative to the working directory after env expansion. +- When `dotnet` is invoked without a DLL, treat as low-confidence and record evidence. +- For single-file executables, read the first few MB looking for bundle markers rather than full PE/ELF parsing. +- Capture runtimeconfig metadata when available; store TFM in `LanguageHit.MainModule`. +- Treat `dotnet exec` wrappers the same as `dotnet `. + +## Evidence & scoring +- Large confidence boost when both host (`dotnet`) and DLL artefact are present. +- Add evidence for runtimeconfig parsing (`"runtimeconfig TFM=net8.0"`), bundle markers, or ASP.NET env vars. +- Penalise detections lacking artefact confirmation. + +## Edge cases +- Native AOT (`dotnet publish -p:PublishAot=true`) emits native binaries without managed markers—should fall back to C/C++ detector. +- PowerShell-launched apps: ShellFlow should rewrite before the detector runs. +- Side-by-side deployment where multiple DLLs exist—prefer the one passed to `dotnet` or specified via `DOTNET_STARTUP_HOOKS`. diff --git a/docs/modules/scanner/operations/entrypoint-lang-elixir.md b/docs/modules/scanner/operations/entrypoint-lang-elixir.md new file mode 100644 index 00000000..2c0a248f --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-elixir.md @@ -0,0 +1,22 @@ +# Entry-Point Runtime — Elixir / Erlang (BEAM) + +## Signals to gather +- `argv0` equals `elixir`, `iex`, `mix`, `erl`, `beam.smp`, or release scripts (`bin/app start`). +- Release layouts: `_build/prod/rel//bin/`, `releases//vm.args`, `sys.config`. +- Environment variables (`MIX_ENV`, `RELEASE_COOKIE`, `RELEASE_NODE`). +- Config files (`config/config.exs`, `config/prod.exs`). + +## Implementation notes +- Recognise Distillery / mix release scripts that `exec` the real BEAM VM. +- When release script is invoked with `eval`, treat the wrapper as part of the chain but classify runtime as `Elixir`. +- Inspect `vm.args` for node name, cookie, and distributed settings. +- For pure Erlang services (no Elixir), the same detector should fire using `erl` hints. + +## Evidence & scoring +- Boost for release directories and BEAM VM binaries (`beam.smp`). +- Add evidence for config files and env vars. +- Penalise minimal images lacking release artefacts (could be generic shell wrappers). + +## Edge cases +- Phoenix apps often rely on `bin/server` wrapper—ShellFlow must collapse to release script. +- Multi-node clusters may start multiple BEAM instances; treat as `Supervisor` if several nodes stay active. diff --git a/docs/modules/scanner/operations/entrypoint-lang-go.md b/docs/modules/scanner/operations/entrypoint-lang-go.md new file mode 100644 index 00000000..d12e75d1 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-go.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — Go + +## Signals to gather +- Statically linked ELF with `.note.go.buildid`. +- `.gopclntab` section (function name table) or `Go build ID` strings. +- Minimal dynamic dependencies (often none) and musl/glibc loader differences. +- `GODEBUG`, `GOMAXPROCS`, `GOENV` environment variables. +- Go module artefacts: `go.mod`, `go.sum`. + +## Implementation notes +- Use ELF parsing to locate `.note.go.buildid`; fallback to scanning the first few MB for `Go build ID`. +- Distinguish from Rust/C by checking `.dynsym` count, presence of Go-specific section names, and the absence of `GLIBCXX`. +- For distroless images, rely solely on ELF traits since no package metadata is present. +- Record binary path and module files as evidence. + +## Evidence & scoring +- Strong boost for `.note.go.buildid` or `.gopclntab`. +- Add evidence for module files or env variables. +- Penalise binaries with high numbers of shared libraries (likely C/C++). + +## Edge cases +- TinyGo or stripped binaries may lack build IDs—fall back to heuristics (symbol patterns, text section). +- CGO-enabled binaries include glibc dependencies; still treat as Go but mention CGO in evidence if detected. +- Supervisors wrapping Go services (e.g., `envoy`) should be handled upstream by wrapper detection. diff --git a/docs/modules/scanner/operations/entrypoint-lang-java.md b/docs/modules/scanner/operations/entrypoint-lang-java.md new file mode 100644 index 00000000..65504eaf --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-java.md @@ -0,0 +1,29 @@ +# Entry-Point Runtime — Java + +## Signals to gather +- `argv0` equals `java` / `javaw` or resides under `*/bin/java`. +- `-jar ` argument with the jar present in the VFS. +- Manifest metadata (`META-INF/MANIFEST.MF`) containing `Main-Class` or `Start-Class`. +- Spring Boot layout (`BOOT-INF/**`). +- Classpath form (`-cp/-classpath`) followed by a main class token. +- Presence of an embedded JRE (`lib/modules`, `jre/bin/java`). +- `JAVA_OPTS`, `JAVA_TOOL_OPTIONS`, or `JAVA_HOME` environment hints. +- `EXPOSE` ports often associated with Java servers (`8080`, `8443`). + +## Implementation notes +- Expand env variables before resolving jar/class paths (supports `${VAR}`, `${VAR:-default}`). +- For classpath mode, open a subset of jars to corroborate `Main-Class`. +- Track when the app is started through shell wrappers (`exec java -jar "$APP_JAR"`); ShellFlow should already collapse these. +- Distinguish between installers (e.g., `java -version`) and actual app launches by checking for jar/class arguments. +- When multiple jars/classes are possible, prefer manifest-backed artefacts but record alternates in evidence. + +## Evidence & scoring +- Reward concrete artefacts (jar exists, manifest resolved). +- Add evidence entries for each heuristic (`"MANIFEST Main-Class=com.example.Main"`, `"Spring Boot BOOT-INF detected"`). +- Penalise missing artefacts or ambiguous classpaths. +- Surface runtime-specific env/ports as supplementary clues, but keep their weight low to avoid false positives. + +## Edge cases +- Launcher scripts that eventually run `java` — ensure ShellFlow surfaces the final command. +- Multi-module fat jars: only expose the main entry jar in evidence; keep supporting jars as context. +- Native image (`native-image` / GraalVM) should fall through to Go/Rust/C++ detectors when `java` binary is absent. diff --git a/docs/modules/scanner/operations/entrypoint-lang-nginx.md b/docs/modules/scanner/operations/entrypoint-lang-nginx.md new file mode 100644 index 00000000..eddbeea3 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-nginx.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — Nginx + +## Signals to gather +- `argv0` equals `nginx`. +- Config files: `/etc/nginx/nginx.conf`, `conf.d/*.conf`, `/usr/share/nginx/html`. +- Environment (`NGINX_ENTRYPOINT_QUIET_LOGS`, `NGINX_PORT`, `NGINX_ENVSUBST_TEMPLATE`). +- Listening sockets on 80/443 (dynamic mode) or `EXPOSE 80` (static). +- Modules or scripts shipped with the official Docker entrypoint (`docker-entrypoint.sh` collapsing to `nginx -g "daemon off;"`). + +## Implementation notes +- Parse `nginx.conf` (basic directive traversal) to extract worker processes, include chains, upstream definitions. +- Handle official entrypoint idioms (`envsubst` templating) via ShellFlow. +- Distinguish pure reverse proxies from PHP-FPM combos; when both `nginx` and `php-fpm` run, classify container as `Supervisor`. +- Record static web content presence (`/usr/share/nginx/html/index.html`). + +## Evidence & scoring +- Boost for confirmed config and workers. +- Add evidence for templating features, env substitution, or modules. +- Penalise if binary exists without config (likely not the entry point). + +## Edge cases +- Alpine images may place configs under `/etc/nginx/conf.d`; include both. +- Custom builds might rename binary (`openresty`, `tengine`); consider aliases if common. +- Windows Nginx not supported; fall back to `Other`. diff --git a/docs/modules/scanner/operations/entrypoint-lang-node.md b/docs/modules/scanner/operations/entrypoint-lang-node.md new file mode 100644 index 00000000..ac1b8355 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-node.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — Node.js + +## Signals to gather +- `argv0` equals `node`, `nodejs`, or path ends with `/bin/node`. +- Scripts launched via package runners (`npm`, `yarn`, `pnpm node …`, `npx`). +- Presence of `package.json` with `"main"` or `"scripts":{"start":…}` entries. +- `NODE_ENV`, `NODE_OPTIONS`, or `NPM_PACKAGE_NAME` environment hints. +- Bundler/PM2 scenarios: `pm2-runtime`, `pm2-docker`, `forever`, `nodemon`. + +## Implementation notes +- Resolve script arguments (e.g., `node server.js`) relative to the working dir. +- If invoked through `npm start`/`yarn run`, parse `package.json` to expand the actual script. +- Support TypeScript loaders (`ts-node`, `node --loader`, `.mjs`) by inspecting extensions and flags. +- Normalise shebang-based Node scripts (ShellFlow ensures `#!/usr/bin/env node` collapses to Node). + +## Evidence & scoring +- Boost confidence when a concrete JS/TS entry file exists. +- Add evidence for `package.json` metadata, PM2 ecosystem files, or `NODE_ENV` values. +- Penalise when the entry file is missing or only package runners are present without scripts. + +## Edge cases +- Multi-service supervisors (e.g., `pm2` managing multiple apps): treat as `Supervisor` and list programmes as children. +- Serverless shims (e.g., Google Functions) wrap Node; prefer the user-provided handler script if detectable. +- Distroless snapshots may omit package managers; rely on Node binary + script presence. diff --git a/docs/modules/scanner/operations/entrypoint-lang-phpfpm.md b/docs/modules/scanner/operations/entrypoint-lang-phpfpm.md new file mode 100644 index 00000000..2378d33c --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-phpfpm.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — PHP-FPM + +## Signals to gather +- `argv0` equals `php-fpm` or `php-fpm8*` variants; master process often invoked with `-F` or `--nodaemonize`. +- Configuration files: `/usr/local/etc/php-fpm.conf`, `www.conf`, pool definitions under `php-fpm.d`. +- PHP runtime artefacts: `composer.json`, `public/index.php`, `artisan`, `wp-config.php`. +- Environment variables such as `PHP_FPM_CONFIG`, `PHP_INI_DIR`, `APP_ENV`. +- Socket or port exposure (`listen = 9000`, `/run/php-fpm.sock`). + +## Implementation notes +- Verify master process vs worker processes (master stays PID 1, workers forked). +- Inspect pool configuration to extract listening endpoint and process manager mode. +- If `docker-php-entrypoint` is involved, ShellFlow must expand to `php-fpm`. +- Distinguish FPM from CLI invocations (`php script.php`) to avoid misclassification. + +## Evidence & scoring +- Reward confirmed config files and listening sockets. +- Add evidence for application artefacts (Composer lockfile, framework directories). +- Penalise when only the binary is present without config (could be CLI usage). + +## Edge cases +- Images bundling Apache/Nginx front-ends should end up as `Supervisor` with PHP-FPM as a child service. +- Some Alpine packages install `php-fpm7` naming—include aliases in detector. +- When `php-fpm` is launched via `s6` or supervisor, rely on child detection to avoid double counting. diff --git a/docs/modules/scanner/operations/entrypoint-lang-python.md b/docs/modules/scanner/operations/entrypoint-lang-python.md new file mode 100644 index 00000000..634aeee5 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-python.md @@ -0,0 +1,25 @@ +# Entry-Point Runtime — Python + +## Signals to gather +- `argv0` equals `python`, `python3`, `pypy`, or an interpreter symlink. +- WSGI/ASGI servers: `gunicorn`, `uvicorn`, `hypercorn`, `daphne`. +- Task runners: `celery -A app worker`, `rq worker`, `pytest`. +- Presence of `requirements.txt`, `pyproject.toml`, `setup.cfg`, or `Pipfile`. +- `PYTHONPATH`, `PYTHONUNBUFFERED`, `DJANGO_SETTINGS_MODULE`, `FLASK_APP`, or application-specific env vars. +- Virtualenv detection (`/venv/bin/python`, `pyvenv.cfg`). + +## Implementation notes +- When invoked as `python -m module`, resolve the module to a path if possible. +- For WSGI/ASGI servers, inspect command arguments (`app:app`, `module:create_app`) and config files. +- Recognise wrapper scripts such as `docker-entrypoint.py` that eventually `exec "$@"`. +- Support zipped apps or single-file bundles by checking `zipapp` signatures. + +## Evidence & scoring +- Increase confidence when module or script exists and dependencies are present. +- Capture evidence for env variables, config files, or known server arguments. +- Penalise ambiguous invocations (e.g., `python -c "..."` without persistent service). + +## Edge cases +- Supervisors launching multiple Python workers fall back to `Supervisor` classification with Python listed as child. +- Conda environments use different directory structures; look for `conda-meta` directories. +- Alpine distroless images may ship `python` symlinks without standard libs—ensure script presence before final classification. diff --git a/docs/modules/scanner/operations/entrypoint-lang-ruby.md b/docs/modules/scanner/operations/entrypoint-lang-ruby.md new file mode 100644 index 00000000..01ba2dc8 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-ruby.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — Ruby + +## Signals to gather +- `argv0` equals `ruby`, `bundle`, `bundler`, `rackup`, `puma`, `unicorn`, `sidekiq`, or `resque`. +- Bundler scripts: `bundle exec `; Gemfile and `Gemfile.lock`. +- Rails and Rack hints: `config.ru`, `bin/rails`, `bin/rake`. +- Background jobs: `sidekiq`, `delayed_job`, `resque`. +- Environment variables (`RAILS_ENV`, `RACK_ENV`, `BUNDLE_GEMFILE`). + +## Implementation notes +- Normalise `bundle exec` by skipping the bundler wrapper and targeting the actual command. +- Resolve script paths relative to the working directory. +- For `puma`/`unicorn`, parse config files (`config/puma.rb`, `config/unicorn.rb`) to gather ports/workers. +- Recognise `foreman start` or `overmind` launching Procfile processes—may devolve to `Supervisor` classification. + +## Evidence & scoring +- Boost confidence when `Gemfile.lock` exists and the requested server script is found. +- Add evidence for env variables and config files. +- Penalise ambiguous CLI invocations or missing artefacts. + +## Edge cases +- Alpine distroless images may rely on `ruby` symlinks; confirm binary presence. +- JRuby (running on Java) may trigger both Ruby and Java signals—prefer Ruby if `ruby`/`jruby` interpreter is explicit. +- Supervisors launching multiple Ruby workers should produce a single `Supervisor` entry with Ruby children. diff --git a/docs/modules/scanner/operations/entrypoint-lang-rust.md b/docs/modules/scanner/operations/entrypoint-lang-rust.md new file mode 100644 index 00000000..8dbec05f --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-rust.md @@ -0,0 +1,24 @@ +# Entry-Point Runtime — Rust + +## Signals to gather +- ELF binaries with DWARF producer strings containing `rustc`. +- Symbols prefixed with `_ZN` (mangled Rust) or section `.rustc`. +- Presence of `panic=abort` strings, `Rust` metadata, or Cargo artefacts (`Cargo.toml`, `Cargo.lock`). +- Statically linked (no `.dynamic` entries) in many cases, or musl loader (`/lib/ld-musl-x86_64.so.1`). +- Environment such as `RUST_LOG`, `RUST_BACKTRACE`. + +## Implementation notes +- Parse DWARF `.debug_info` when available; short-circuit by scanning `.comment` sections for `rustc`. +- Distinguish from Go by the absence of `.note.go.buildid`. +- When Cargo artefacts exist, include target name and profile in evidence. +- For binaries built with `--target x86_64-pc-windows-gnu`, treat them under the same detector (PE + Rust markers). + +## Evidence & scoring +- Reward DWARF producer strings, Cargo files, and Rust-specific env vars. +- Penalise when only generic static binary traits are present (may defer to C/C++). +- Mention musl vs glibc loader differences for observability. + +## Edge cases +- Rust compiled to WebAssembly or run inside Wasmtime falls outside this detector; leave as `Other`. +- Stripped binaries without DWARF or comments may be indistinguishable from C—fall back to C/C++ and add note. +- Supervisors launching multiple Rust binaries handled upstream. diff --git a/docs/modules/scanner/operations/entrypoint-lang-supervisor.md b/docs/modules/scanner/operations/entrypoint-lang-supervisor.md new file mode 100644 index 00000000..0f2d5dc4 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-lang-supervisor.md @@ -0,0 +1,25 @@ +# Entry-Point Runtime — Supervisors + +Some containers intentionally launch multiple long-lived services (sidecars, appliance images, `supervisord`, `s6`, `runit`, `pm2`). Instead of forcing a single runtime classification, the detector can emit a `Supervisor` entry with child services enumerated separately. + +## Signals to gather +- Known supervisor binaries: `supervisord`, `s6-svscan`, `s6-supervise`, `runsvdir`, `pm2-runtime`, `forego`, `foreman`, `overmind`. +- Configuration files: `/etc/supervisord.conf`, `/etc/s6/*.conf`, `Procfile`, `ecosystem.config.js`. +- Multiple child processes that remain active after startup. +- Environment variables controlling supervisor behaviour (`SUPERVISOR_*`, `PM2_HOME`, `S6_CMD_WAIT_FOR_SERVICES`). + +## Implementation notes +- Keep the supervisor as the primary terminal but query configuration to list child commands. +- For each child, run the usual reduction + runtime detection and attach results as derived evidence. +- When configuration is templated (e.g., `envsubst`), evaluate ShellFlow output to resolve final commands. +- Record scheduling details (autorestart, process limits) relevant for incident response. + +## Evidence & scoring +- Supervisor detection flips `LanguageType.Supervisor` with mid-level confidence (0.6–0.7). +- Confidence increases when configuration explicitly lists services and child processes are observed (dynamic mode). +- Provide evidence for each child service (`"manages: php-fpm on /run/php-fpm.sock"`, `"manages: nginx listening on 0.0.0.0:80"`). + +## Edge cases +- Docker Compose-style images using `bash` to run multiple services should also map here if ShellFlow detects multiple `&` background jobs. +- Ensure we do not classify minimal init shims (`tini`, `dumb-init`) as supervisors—they should be collapsed. +- When supervisor manages only one child, collapse to the child runtime and drop the supervisor evidence to avoid noise. diff --git a/docs/modules/scanner/operations/entrypoint-problem.md b/docs/modules/scanner/operations/entrypoint-problem.md new file mode 100644 index 00000000..e451cb83 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-problem.md @@ -0,0 +1,94 @@ +# Entry-Point Detection — Problem & Architecture + +## 1) Why this exists + +Container images rarely expose their *real* workload directly. Shell wrappers, init shims, supervisors, or language launchers often sit between the Dockerfile `ENTRYPOINT`/`CMD` values and the program you actually care about. Stella Ops needs a deterministic, explainable way to map any container image (or running container) to a single logical entry point that downstream systems can reason about. + +We define the target artefact as the tuple below: + +```jsonc +{ + "type": "java|dotnet|go|python|node|ruby|php-fpm|c/c++|rust|nginx|supervisor|other", + "resolvedBinary": "/app/app.jar | /app/app.dll | /app/server | /usr/local/bin/node", + "args": ["..."], + "confidence": 0.00..1.00, + "evidence": [ + "why we believe this" + ], + "chain": [ + {"from": "/bin/sh -c", "to": "/entrypoint.sh", "why": "ENTRYPOINT shell-form"}, + {"from": "/entrypoint.sh", "to": "java -jar orders.jar", "why": "exec \"$@\" with java default"} + ] +} +``` + +Constraints: + +- Static first: no `/proc`, no `ptrace`, no customer code execution when scanning images. +- Honour Docker/OCI precedence (`ENTRYPOINT` vs `CMD`, shell- vs exec-form, Windows `Shell` overrides). +- Work on distroless and multi-arch images as well as traditional distro bases. +- Emit auditable evidence and reduction chains so policy decisions are explainable. + +## 2) Dual-mode architecture + +The scanner exposes a single façade but routes to two reducers: + +``` +Scanner.EntryTrace/ + Common/ + OciImageReader.cs + OverlayVfs.cs + Heuristics/ + Models/ + Dynamic/ProcReducer.cs // running container + Static/ImageReducer.cs // static image inference +``` + +Selection logic: + +```csharp +IEntryReducer reducer = container.IsRunning + ? new ProcReducer() + : new ImageReducer(); +var result = reducer.TraceAndReduce(ct); +``` + +Both reducers publish a harmonised `EntryTraceResult`, allowing downstream modules (Policy Engine, Vuln Explorer, Export Center) to consume the same shape regardless of data source. + +## 3) Pipeline overview + +### 3.1 Static images + +1. Pull or load OCI image. +2. Compose final argv (`ENTRYPOINT ++ CMD`), respecting shell overrides. +3. Overlay layers with whiteout support via a lazy virtual filesystem. +4. Resolve paths, shebangs, wrappers, and scripts until a terminal candidate emerges. +5. Classify runtime family, identify application artefact, score confidence, and emit evidence. + +### 3.2 Running containers + +1. Capture real exec / fork events and build an exec graph. +2. Locate steady-state processes (long-lived, owns listeners, not a shim). +3. Collapse wrappers using the same catalogue as static mode. +4. Cross-check with static heuristics to tighten confidence. + +### 3.3 Shared components + +- **ShellFlow static analyser** handles script idioms (`set --`, `exec "$@"`, branch rewrites). +- **Wrapper catalogue** recognises shells, init shims, supervisors, and package runners. +- **Runtime detectors** plug in per language/framework (Java, .NET, Node, Python, PHP-FPM, Ruby, Go, Rust, Nginx, C/C++). +- **Score calibrator** turns detector raw scores into a unified 0..1 confidence. + +## 4) Document map + +The entry-point playbook is now split into focused guides: + +| Document | Purpose | +| --- | --- | +| `entrypoint-static-analysis.md` | Overlay VFS, argv composition, wrapper reduction, scoring. | +| `entrypoint-dynamic-analysis.md` | Observational Exec Graph for running containers. | +| `entrypoint-shell-analysis.md` | ShellFlow static analyser and script idioms. | +| `entrypoint-runtime-overview.md` | Detector contracts, helper utilities, calibration, integrations. | +| `entrypoint-lang-*.md` | Runtime-specific heuristics (Java, .NET, Node, Python, PHP-FPM, Ruby, Go, Rust, C/C++, Nginx, Deno, Elixir/BEAM, Supervisor). | + +Use this file as the landing page; each guide can be read independently when implementing or updating a specific component. diff --git a/docs/modules/scanner/operations/entrypoint-runtime-overview.md b/docs/modules/scanner/operations/entrypoint-runtime-overview.md new file mode 100644 index 00000000..a506dc90 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-runtime-overview.md @@ -0,0 +1,152 @@ +# Runtime Detector Overview + +Runtime classification converts a reduced command into a concrete language or framework identity with supporting evidence. This document describes the shared contracts, helper utilities, calibration strategy, and integration points; language-specific heuristics live in the `entrypoint-lang-*.md` files. + +## 1) Contracts + +```csharp +public enum LanguageType { + Java, DotNet, Node, Python, PhpFpm, Ruby, Go, Rust, CCpp, + Nginx, Deno, Elixir, Supervisor, Other +} + +public sealed record ResolvedCommand( + string[] Argv, + string Argv0, + string? AbsolutePath, + bool IsElf, + bool IsPe, + bool IsScript, + string? Shebang, + string WorkingDir +); + +public sealed record LanguageHit( + LanguageType Type, + double RawScore, + string ResolvedBinary, + string[] Args, + List Evidence, + string? AppArtifactPath = null, + string? MainModule = null, + Dictionary? Extra = null +); +``` + +### Interface + +```csharp +public interface ILanguageSubDetector { + LanguageHit? TryDetect( + ResolvedCommand cmd, OverlayVfs vfs, EnvBag env, ImageContext img, CancellationToken ct = default); +} + +public sealed class LanguageDetector { + private readonly ILanguageSubDetector[] _detectors = { + new JavaDetector(), + new DotNetDetector(), + new NodeDetector(), + new PythonDetector(), + new PhpFpmDetector(), + new RubyDetector(), + new NginxDetector(), + new GoDetector(), + new RustDetector(), + new DenoDetector(), + new ElixirDetector(), + new CCppDetector(), + new SupervisorDetector() + }; + private readonly ScoreCalibrator _cal = ScoreCalibrator.Default; + + public LanguageHit Detect(ResolvedCommand cmd, OverlayVfs vfs, EnvBag env, ImageContext img, out double confidence) { + var hits = _detectors.Select(d => d.TryDetect(cmd, vfs, env, img)).Where(h => h is not null).ToList()!; + LanguageHit best = hits.Count == 0 + ? new LanguageHit(LanguageType.Other, 0.10, cmd.AbsolutePath ?? cmd.Argv0, cmd.Argv.Skip(1).ToArray(), + new() { "No strong runtime family signals detected." }) + : hits.OrderByDescending(_cal.Calibrate).First(); + + confidence = _cal.Calibrate(best); + foreach (var alt in hits.Where(h => h != best).OrderByDescending(_cal.Calibrate)) + best.Evidence.Add($"Alternative: {alt!.Type} (score={_cal.Calibrate(alt):0.00}) — {string.Join("; ", alt.Evidence.Take(2))}…"); + return best; + } +} +``` + +## 2) Helpers + +```csharp +static class VfsHelpers { + public static bool FileExists(OverlayVfs vfs, string path) => vfs.Exists(path); + public static bool TryOpen(OverlayVfs vfs, string path, out Stream? stream) { + if (!vfs.Exists(path)) { stream = null; return false; } + stream = vfs.OpenRead(path); + return true; + } + public static string Join(string cwd, string maybeRel) => + Path.IsPathRooted(maybeRel) ? maybeRel : Path.GetFullPath(Path.Combine(cwd, maybeRel)); +} + +static class ArgvHelpers { + public static int IndexOf(this string[] argv, string flag) => + Array.FindIndex(argv, a => a == flag); + public static string? Next(this string[] argv, int idx) => + (idx >= 0 && idx + 1 < argv.Length) ? argv[idx + 1] : null; + public static bool AnyEndsWith(this IEnumerable args, string suffix, bool ignoreCase = true) => + args.Any(a => a.EndsWith(suffix, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)); + public static bool Is(this string? candidate, params string[] names) => + candidate is not null && names.Any(n => string.Equals(Path.GetFileName(candidate), n, StringComparison.OrdinalIgnoreCase)); +} +``` + +## 3) Scoring & calibration + +- Each sub-detector returns a `RawScore` (0..1) based on family-specific heuristics. +- Feed raw scores into a calibrator (Platt scaling or isotonic regression) trained on labelled corpora to get calibrated probabilities. +- Persist calibration metadata per detector to avoid drift. +- When no detector fires, return `LanguageType.Other` with low confidence and an evidence note. + +## 4) Cross-checks + +Enhance precision by combining detector results with filesystem and configuration signals: + +- Compare declared `EXPOSE` ports with runtime defaults (e.g., `80/443` for Nginx, `8080` for Java app servers). +- Inspect service-specific configuration (`nginx.conf`, `php-fpm.conf`, `web.config`, `Gemfile`, `package.json`, `pyproject.toml`). +- For Java and .NET, verify artefact presence and manifest metadata; for Go/Rust check static binary traits. +- Re-run detectors after ShellFlow rewrites to ensure post-`exec` commands are analysed. + +## 5) Windows nuances + +- Use `config.Shell` to detect PowerShell vs CMD; adjust interpreter lookup accordingly. +- PE probing is mandatory—PowerShell scripts often front .NET or native binaries. +- Consider case-insensitive paths and `\` separators. + +## 6) Integration points + +- Static reducer passes `ResolvedCommand` → runtime detector. +- Dynamic reducer pipes steady-state commands through the same interface. +- Output `LanguageHit` populates the `TerminalProcess` along with `confidence`. +- Downstream consumers (Policy Engine, Vuln Explorer) merge runtime type into their evidence trail. + +## 7) Next steps + +Language-specific heuristics live in: + +| Runtime | Document | +| --- | --- | +| Java | `entrypoint-lang-java.md` | +| .NET / C# | `entrypoint-lang-dotnet.md` | +| Node.js | `entrypoint-lang-node.md` | +| Python | `entrypoint-lang-python.md` | +| PHP-FPM | `entrypoint-lang-phpfpm.md` | +| Ruby | `entrypoint-lang-ruby.md` | +| Go | `entrypoint-lang-go.md` | +| Rust | `entrypoint-lang-rust.md` | +| C/C++ | `entrypoint-lang-ccpp.md` | +| Nginx | `entrypoint-lang-nginx.md` | +| Deno | `entrypoint-lang-deno.md` | +| Elixir/Erlang (BEAM) | `entrypoint-lang-elixir.md` | +| Supervisors | `entrypoint-lang-supervisor.md` | + +Each runtime file documents the heuristics, artefacts, and edge cases specific to that family. diff --git a/docs/modules/scanner/operations/entrypoint-shell-analysis.md b/docs/modules/scanner/operations/entrypoint-shell-analysis.md new file mode 100644 index 00000000..ba91baae --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-shell-analysis.md @@ -0,0 +1,83 @@ +# ShellFlow — Script Reduction Playbook + +Most container entry points eventually execute a shell script. The ShellFlow analyser resolves these scripts without executing user code, providing deterministic, explainable reductions. + +## 1) Scope + +- POSIX `sh` subset with common Bash extensions (control flow, functions, parameter expansion). +- Handles idioms from official Docker images (`if [ "$1" = "server" ]; then …`, `exec gosu "$USER" "$@"`, `set -- java -jar …`). +- Tracks positional parameters (`$@`, `$1..$9`), environment variables, and `set --` mutations. +- Produces one or more candidate commands with supporting evidence. + +## 2) Architecture + +``` +ShellFlow/ + Parser/ // POSIX sh lexer + recursive descent parser + Ast/ // nodes for lists, pipelines, conditionals, functions + Evaluator/ // partial evaluation & taint tracking + Idioms/ // pattern library for common Docker entrypoints + Planner/ // emits CommandPlan[] +``` + +### 2.1 CommandPlan + +```csharp +public sealed record CommandPlan( + string[] Argv, + double HeuristicScore, + IReadOnlyList Evidence, + IReadOnlyList Chain, + bool IsFallback = false +); +``` + +Plans feed directly into the static reducer, which selects the highest-confidence plan but keeps alternates as evidence. + +## 3) Parsing & AST + +- Tokenise words, assignments, pipelines (`|`), lists (`;`, `&&`, `||`), conditionals (`if`, `case`), loops (`for`, `while`, `until`), functions, and redirections. +- Preserve heredocs and subshells as opaque nodes (evaluated conservatively). +- Record source spans to surface meaningful evidence (`"line 12: exec java -jar $APP_JAR"`). + +## 4) Partial evaluation + +- Initialise symbol table from image environment plus caller-supplied args. +- Treat `$@`, `$*`, `$1..$9` as tainted; propagate taint through assignments. +- Resolve `${VAR:-default}` and `${VAR:+alt}` when `VAR` known; otherwise branch. +- Support `set -- …` (resets positional parameters) and `shift`. +- `source`/`.` commands are parsed recursively when files are available; else fallback to low-confidence branch. + +## 5) Exec sink detection + +- `exec ` dominates the remainder of the script. +- Chains such as `exec gosu "$USER" "$@"` feed into wrapper collapse. +- When no `exec` is present, pick the last reachable simple command in the main path. +- Multi-branch scripts yield multiple plans with adjusted scores; unresolved branches are marked `IsFallback`. + +## 6) Idiom library + +| Pattern | Action | +| --- | --- | +| `if [ "${1:0:1}" = '-' ]; then set -- server "$@"; fi` | Rewrite argv to prepend default command. | +| `if [ "$1" = "bash" ]; then exec "$@"; fi` | Pass-through for manual shells. | +| `exec "$@"` + non-empty CMD | Substitute CMD vector into plan. | +| `exec java -jar "$APP_JAR" "$@"` | Resolve JAR via env or filesystem. | +| `set -- gosu "$APP_USER" "$@"` | Collapse into wrapper plan. | + +Idioms are implemented as AST visitors; each adds evidence strings when triggered. + +## 7) Confidence scoring + +- Base score from plan heuristics (`HeuristicScore`). +- Penalties for unresolved taint (`$@` unknown), missing files, nested subshells, or fallbacks. +- Bonus when idioms match, artefacts exist, or env values resolve cleanly. +- Final confidence is combined with the outer static scoring model. + +## 8) Failure modes + +- Missing script (`ENTRYPOINT` points to deleted file): emit fallback plan with low confidence. +- Self-modifying scripts or heavy dynamic features (`eval`, backticks): mark plan as low-confidence and surface warning evidence. +- Commands that spawn supervisors without `exec`: return both the supervisor and inferred children (if configuration files are present). + +ShellFlow keeps the static reducer explainable: every inferred command is accompanied by the script span and reasoning used to reach it. diff --git a/docs/modules/scanner/operations/entrypoint-static-analysis.md b/docs/modules/scanner/operations/entrypoint-static-analysis.md new file mode 100644 index 00000000..3a83c208 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint-static-analysis.md @@ -0,0 +1,122 @@ +# Entry-Point Static Analysis + +This guide captures the static half of Stella Ops’ entry-point detection pipeline: how we turn image metadata and filesystem contents into a resolved binary, an execution chain, and a confidence score. + +## 1) Loading OCI images + +### 1.1 Supported inputs +- Registry references (`repo:tag@sha256:digest`) using the existing content store. +- Local OCI/Docker v2 archives (`docker save` tarball, OCI layout directory with `index.json` + `blobs/sha256/*`). + +### 1.2 Normalised model + +```csharp +sealed class OciImage { + public required string Os; + public required string Arch; + public required string[] Entrypoint; + public required string[] Cmd; + public required string[] Shell; // Windows / powershell overrides + public required string WorkingDir; + public required string[] Env; + public required string[] ExposedPorts; + public required LabelMap Labels; + public required LayerRef[] Layers; // ordered, compressed blobs +} +``` + +Compose the runtime argv as `Entrypoint ++ Cmd`, honouring shell-form vs exec-form (see §2.3). + +## 2) Overlay virtual filesystem + +### 2.1 Whiteouts +- Regular whiteout: `path/.wh.` removes `` from lower layers. +- Opaque directory: `path/.wh..wh..opq` hides the directory entirely. + +### 2.2 Lazy extraction +- First pass: build a tar index `(path → layer, offset, size, mode, isWhiteout, isDir)`. +- Decompress only when reading a file; optionally support eStargz TOC to accelerate random access. + +### 2.3 Shell-form composition +- Dockerfile shell form is serialised as `["/bin/sh","-c","…"]` (or `Shell[]` override on Windows). +- Always trust `config.json`; no need to inspect the Dockerfile. +- Working directory defaults to `/` if unspecified. + +## 3) Low-level primitives + +### 3.1 PATH resolution +- Extract `PATH` from environment (fallback `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`). +- If `argv[0]` is relative or lacks `/`, walk the PATH to resolve an absolute file. +- Verify execute bit (or Windows ACL) before accepting. + +### 3.2 Shebang handling +- For non-ELF/PE files: read first line; interpret `#!interpreter args`. +- Replace `argv[0]` with the interpreter, prepend shebang args, append script path per kernel semantics. + +### 3.3 Binary probes +- Identify ELF via magic `\x7FELF`, parse `.interp`, `.dynamic`, linked libs, `.note.go.buildid`, DWARF producer. +- Identify PE (Windows) and detect .NET single-file bundles via CLI header. +- Record features for runtime scoring (Go vs Rust vs glibc vs musl). + +## 4) Wrapper catalogue + +Collapse known wrappers before analysing the target command: + +- Init shims: `tini`, `dumb-init`, `s6-svscan`, `runit`, `supervisord`. +- Privilege droppers: `gosu`, `su-exec`, `chpst`. +- Shells: `sh`, `bash`, `dash`, BusyBox variants. +- Package runners: `npm`, `yarn`, `pnpm`, `pip`, `pipenv`, `poetry`, `bundle`, `rake`. + +Rules: +- If wrapper contains a `--` sentinel (`tini -- app …`) drop the wrapper and record a reduction edge. +- `gosu user cmd …` → collapse to `cmd …`. +- For shell wrappers, delegate to the ShellFlow analyser (see separate guide). + +## 5) ShellFlow integration + +When the resolved command is a shell script, invoke the ShellFlow analyser to locate the eventual `exec` target. Key capabilities: + +- Parses POSIX sh (and common Bash extensions). +- Tracks environment mutations (`set`, `export`, `set --`). +- Resolves `$@`, `$1..9`, `${VAR:-default}`. +- Recognises idioms from official Docker images (`if [ "$1" = "server" ]; then …`). +- Emits multiple branches when predicates depend on unknown data, but tags them with lower confidence. + +The analyser returns one or more candidate commands along with reasons, which feed into the reduction engine. + +## 6) Reduction algorithm + +1. Compose argv `ENTRYPOINT ++ CMD`. +2. Collapse wrappers; append `ReductionEdge` entries documenting each step. +3. Resolve argv0 to an absolute file and classify (ELF/PE/script). +4. If script → run ShellFlow; replace current command with highest-confidence `exec` target while preserving alternates as evidence. +5. Attempt to resolve application artefacts for VM hosts (JARs, DLLs, JS entry, Python module, etc.). +6. Emit `EntryTraceResult` with candidate terminals ranked by confidence. + +## 7) Confidence scoring + +Use a simple logistic model with feature contributions captured for the evidence trail. Example features: + +| Id | Signal | Weight | +| --- | --- | --- | +| `f1` | Entrypoint already an executable (ELF/PE) | +0.18 | +| `f2` | Observed chain ends in non-wrapper binary | +0.22 | +| `f3` | VM host + resolvable artefact | +0.20 | +| `f4` | Exposed ports align with runtime | +0.06 | +| `f5` | Shebang interpreter matches runtime family | +0.05 | +| `f6` | Language artefact validation succeeded | +0.15 | +| `f8` | Multi-branch script unresolved (`$@` taint) | −0.20 | +| `f9` | Target missing execute bit | −0.25 | +| `f10` | Shell with no `exec` | −0.18 | + +Persist per-feature evidence strings so UI/CLI users can see **why** the scanner picked a given entry point. + +## 8) Outputs + +Return a populated `EntryTraceResult`: + +- `Terminals` contains the best candidate(s) and their runtime classification. +- `Evidence` aggregates feature messages, ShellFlow reasoning, wrapper reductions, and runtime detector hints. +- `Chain` shows the explainable path from initial Docker argv to the final binary. + +Static and dynamic reducers share this shape, enabling downstream modules to remain agnostic of the detection mode. diff --git a/docs/modules/scanner/operations/entrypoint.md b/docs/modules/scanner/operations/entrypoint.md new file mode 100644 index 00000000..40aa1e53 --- /dev/null +++ b/docs/modules/scanner/operations/entrypoint.md @@ -0,0 +1,26 @@ +# Entry-Point Documentation Index + +The entry-point detection system is now split into focused guides. Use this index to navigate the individual topics. + +| Topic | Document | +| --- | --- | +| Problem statement & architecture overview | `entrypoint-problem.md` | +| Static resolver (OCI layers, wrappers, scoring) | `entrypoint-static-analysis.md` | +| Dynamic resolver / Observational Exec Graph | `entrypoint-dynamic-analysis.md` | +| ShellFlow script analysis | `entrypoint-shell-analysis.md` | +| Runtime detector contracts & calibration | `entrypoint-runtime-overview.md` | +| Java heuristics | `entrypoint-lang-java.md` | +| .NET heuristics | `entrypoint-lang-dotnet.md` | +| Node.js heuristics | `entrypoint-lang-node.md` | +| Python heuristics | `entrypoint-lang-python.md` | +| PHP-FPM heuristics | `entrypoint-lang-phpfpm.md` | +| Ruby heuristics | `entrypoint-lang-ruby.md` | +| Go heuristics | `entrypoint-lang-go.md` | +| Rust heuristics | `entrypoint-lang-rust.md` | +| C/C++ heuristics | `entrypoint-lang-ccpp.md` | +| Nginx heuristics | `entrypoint-lang-nginx.md` | +| Deno heuristics | `entrypoint-lang-deno.md` | +| Elixir / Erlang (BEAM) heuristics | `entrypoint-lang-elixir.md` | +| Supervisor classification | `entrypoint-lang-supervisor.md` | + +> Looking for historical context? The unified write-up previously in `entrypoint2.md` and `entrypoint-lang-detection.md` has been decomposed into the files above for easier maintenance. diff --git a/docs/ops/scanner-rustfs-migration.md b/docs/modules/scanner/operations/rustfs-migration.md similarity index 98% rename from docs/ops/scanner-rustfs-migration.md rename to docs/modules/scanner/operations/rustfs-migration.md index 28d8081d..4062b7d6 100644 --- a/docs/ops/scanner-rustfs-migration.md +++ b/docs/modules/scanner/operations/rustfs-migration.md @@ -23,7 +23,7 @@ deployments, capture an external backup (e.g., `mc mirror` to offline storage). ## 2. Dry-run the migrator ``` -dotnet run --project tools/RustFsMigrator -- \ +dotnet run --project src/Tools/RustFsMigrator -- \ --s3-bucket scanner-artifacts \ --s3-endpoint http://stellaops-minio:9000 \ --s3-access-key stellaops \ diff --git a/docs/modules/scheduler/AGENTS.md b/docs/modules/scheduler/AGENTS.md new file mode 100644 index 00000000..df117961 --- /dev/null +++ b/docs/modules/scheduler/AGENTS.md @@ -0,0 +1,22 @@ +# Scheduler agent guide + +## Mission +Scheduler detects advisory/VEX deltas, computes impact windows, and orchestrates re-evaluations across Scanner and Policy Engine. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/scheduler/README.md b/docs/modules/scheduler/README.md new file mode 100644 index 00000000..240d61f2 --- /dev/null +++ b/docs/modules/scheduler/README.md @@ -0,0 +1,37 @@ +# StellaOps Scheduler + +Scheduler detects advisory/VEX deltas, computes impact windows, and orchestrates re-evaluations across Scanner and Policy Engine. + +## Responsibilities +- Maintain impact cursors and queues for re-scan/re-evaluate jobs. +- Expose APIs for policy-triggered rechecks and runtime hooks. +- Emit DSSE-backed completion events for downstream consumers (UI, Notify). +- Provide SLA-aware retry logic with deterministic evaluation windows. + +## Key components +- `StellaOps.Scheduler.WebService` control plane. +- `StellaOps.Scheduler.Worker` job executor. +- Shared libraries under `StellaOps.Scheduler.*`. + +## Integrations & dependencies +- MongoDB for impact models. +- Redis/NATS for queueing. +- Policy Engine, Scanner, Notify. + +## Operational notes +- Monitoring assets in ./operations/worker-grafana-dashboard.json & worker-prometheus-rules.yaml. +- Operational runbook ./operations/worker.md. + +## Related resources +- ./operations/worker.md +- ./operations/worker-grafana-dashboard.json +- ./operations/worker-prometheus-rules.yaml + +## Backlog references +- SCHED-MODELS-20-001 (policy run DTOs) and related tasks in ../../TASKS.md. +- Scheduler observability follow-ups in src/Scheduler/**/TASKS.md. + +## Epic alignment +- **Epic 2 – Policy Engine & Editor:** orchestrate incremental re-evaluation and simulation runs when raw facts or policies change. +- **Epic 6 – Vulnerability Explorer:** feed triage workflows with up-to-date job status, explain traces, and ledger hooks. +- **Epic 9 – Orchestrator Dashboard:** expose job telemetry, throttling, and replay controls through orchestration dashboards. diff --git a/docs/modules/scheduler/TASKS.md b/docs/modules/scheduler/TASKS.md new file mode 100644 index 00000000..45aee164 --- /dev/null +++ b/docs/modules/scheduler/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Scheduler + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| SCHEDULER-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| SCHEDULER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| SCHEDULER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_SCHEDULER.md b/docs/modules/scheduler/architecture.md similarity index 96% rename from docs/ARCHITECTURE_SCHEDULER.md rename to docs/modules/scheduler/architecture.md index 21e4d60a..02842e90 100644 --- a/docs/ARCHITECTURE_SCHEDULER.md +++ b/docs/modules/scheduler/architecture.md @@ -1,4 +1,6 @@ -# component_architecture_scheduler.md — **Stella Ops Scheduler** (2025Q4) +# component_architecture_scheduler.md — **Stella Ops Scheduler** (2025Q4) + +> Synthesises the scheduling requirements documented across the Policy, Vulnerability Explorer, and Orchestrator module guides and implementation plans. > **Scope.** Implementation‑ready architecture for **Scheduler**: a service that (1) **re‑evaluates** already‑cataloged images when intel changes (Feedser/Vexer/policy), (2) orchestrates **nightly** and **ad‑hoc** runs, (3) targets only the **impacted** images using the BOM‑Index, and (4) emits **report‑ready** events that downstream **Notify** fans out. Default mode is **analysis‑only** (no image pull); optional **content‑refresh** can be enabled per schedule. diff --git a/docs/modules/scheduler/implementation_plan.md b/docs/modules/scheduler/implementation_plan.md new file mode 100644 index 00000000..1038d2a1 --- /dev/null +++ b/docs/modules/scheduler/implementation_plan.md @@ -0,0 +1,21 @@ +# Implementation plan — Scheduler + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 2 – Policy Engine & Editor:** deliver incremental policy run orchestration, change streams, and explain trace propagation. +- **Epic 6 – Vulnerability Explorer:** ensure findings updates and remediation triggers integrate with scheduler outputs. +- **Epic 9 – Orchestrator Dashboard:** provide job telemetry and control surfaces consumed by the orchestrator UI/CLI. +- Track additional work (SCHED-MODELS-20-001, observability follow-ups) in ../../TASKS.md and src/Scheduler/**/TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ops/scheduler-worker-grafana-dashboard.json b/docs/modules/scheduler/operations/worker-grafana-dashboard.json similarity index 100% rename from docs/ops/scheduler-worker-grafana-dashboard.json rename to docs/modules/scheduler/operations/worker-grafana-dashboard.json diff --git a/docs/ops/scheduler-worker-prometheus-rules.yaml b/docs/modules/scheduler/operations/worker-prometheus-rules.yaml similarity index 100% rename from docs/ops/scheduler-worker-prometheus-rules.yaml rename to docs/modules/scheduler/operations/worker-prometheus-rules.yaml diff --git a/docs/ops/scheduler-worker-operations.md b/docs/modules/scheduler/operations/worker.md similarity index 91% rename from docs/ops/scheduler-worker-operations.md rename to docs/modules/scheduler/operations/worker.md index 99e8850a..e880ac4a 100644 --- a/docs/ops/scheduler-worker-operations.md +++ b/docs/modules/scheduler/operations/worker.md @@ -3,7 +3,7 @@ ## Purpose Monitor planner and runner health for the Scheduler Worker (Sprint 16 telemetry). The new .NET meters surface queue throughput, latency, backlog, and delta severities so operators can detect stalled runs before rescan SLAs slip. -> **Grafana note:** Import `docs/ops/scheduler-worker-grafana-dashboard.json` into the Prometheus-backed Grafana stack that scrapes the OpenTelemetry Collector. +> **Grafana note:** Import `docs/modules/scheduler/operations/worker-grafana-dashboard.json` into the Prometheus-backed Grafana stack that scrapes the OpenTelemetry Collector. --- @@ -24,7 +24,7 @@ Reference queries power the bundled Grafana dashboard panels. Use the `mode` tem ## Grafana dashboard -1. Import `docs/ops/scheduler-worker-grafana-dashboard.json` (UID `scheduler-worker-observability`). +1. Import `docs/modules/scheduler/operations/worker-grafana-dashboard.json` (UID `scheduler-worker-observability`). 2. Point the `datasource` variable to the Prometheus instance scraping the collector. Optional: pin the `mode` variable to a specific schedule mode. 3. Panels included: - **Planner Runs per Status** – visualises success vs failure ratio. @@ -40,7 +40,7 @@ Capture screenshots once Grafana provisioning completes and store them under `do ## Prometheus alerts -Import `docs/ops/scheduler-worker-prometheus-rules.yaml` into your Prometheus rule configuration. The bundle defines: +Import `docs/modules/scheduler/operations/worker-prometheus-rules.yaml` into your Prometheus rule configuration. The bundle defines: - **SchedulerPlannerFailuresHigh** – 5%+ of planner runs failed for 10 minutes. Page SRE. - **SchedulerPlannerLatencyHigh** – planner p95 latency remains above 45 s for 10 minutes. Investigate ImpactIndex, Mongo, and Feedser/Vexer event queues. diff --git a/docs/modules/signer/AGENTS.md b/docs/modules/signer/AGENTS.md new file mode 100644 index 00000000..707d65bf --- /dev/null +++ b/docs/modules/signer/AGENTS.md @@ -0,0 +1,22 @@ +# Signer agent guide + +## Mission +Signer validates callers, enforces Proof-of-Entitlement, and produces signed DSSE bundles for SBOMs, reports, and exports. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. diff --git a/docs/modules/signer/README.md b/docs/modules/signer/README.md new file mode 100644 index 00000000..cf2e6a52 --- /dev/null +++ b/docs/modules/signer/README.md @@ -0,0 +1,30 @@ +# StellaOps Signer + +Signer validates callers, enforces Proof-of-Entitlement, and produces signed DSSE bundles for SBOMs, reports, and exports. + +## Responsibilities +- Enforce plan quotas and PoE before signing artifacts. +- Support keyless and keyful signing backends. +- Emit DSSE payloads consumed by Attestor and downstream bundles. +- Maintain audit trails for all signing operations. + +## Key components +- `StellaOps.Signer` service host. +- Crypto providers under `StellaOps.Cryptography.*`. + +## Integrations & dependencies +- Authority for OpTok validation. +- Attestor for transparency logging. +- Export Center and CLI for artifact signing flows. + +## Operational notes +- Key management via Authority/DevOps runbooks. +- Metrics for signing latency/throttle states. +- Offline kit integration for signature verification. + +## Backlog references +- SIG docs/tasks in ../../TASKS.md (e.g., DOCS-SIG-26-006). + +## Epic alignment +- **Epic 10 – Export Center:** provide signing pipelines, cosign interoperability, and provenance manifests for bundle promotion. +- **Epic 19 – Attestor Console:** supply DSSE payloads and Proof-of-Entitlement enforcement feeding attestation workflows described in `docs/modules/attestor/`. diff --git a/docs/modules/signer/TASKS.md b/docs/modules/signer/TASKS.md new file mode 100644 index 00000000..11a421cf --- /dev/null +++ b/docs/modules/signer/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Signer + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| SIGNER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| SIGNER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| SIGNER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_SIGNER.md b/docs/modules/signer/architecture.md similarity index 99% rename from docs/ARCHITECTURE_SIGNER.md rename to docs/modules/signer/architecture.md index b116f879..56028960 100644 --- a/docs/ARCHITECTURE_SIGNER.md +++ b/docs/modules/signer/architecture.md @@ -1,5 +1,7 @@ # component_architecture_signer.md — **Stella Ops Signer** (2025Q4) +> Supports deliverables from Epic 10 – Export Center and Epic 19 – Attestor Console. + > **Scope.** Implementation‑ready architecture for the **Signer**: the *only* service allowed to produce **Stella Ops‑verified** signatures over SBOMs and reports. It enforces **entitlement** (PoE), **release integrity** (scanner provenance), **sender‑constrained auth** (DPoP/mTLS), and emits **in‑toto/DSSE** bundles suitable for **Rekor v2** logging by the Attestor. Includes APIs, data flow, storage, quotas, security, and test matrices. --- diff --git a/docs/modules/signer/implementation_plan.md b/docs/modules/signer/implementation_plan.md new file mode 100644 index 00000000..c0877a14 --- /dev/null +++ b/docs/modules/signer/implementation_plan.md @@ -0,0 +1,61 @@ +# Implementation plan — Signer + +## Delivery phases +- **Phase 1 – Core service & PoE** + Harden OpTok validation, Proof-of-Entitlement (PoE) checks, quota enforcement, scanner release verification, and DSSE signing pipeline (keyless + keyful). +- **Phase 2 – Export Center integration** + Produce signing bundles with provenance manifests for Export Center, deliver cosign-compatible outputs, and document verification workflows for offline exports. +- **Phase 3 – Attestor alignment** + Emit DSSE envelopes, metadata, and signer identity information required by Attestor (key metadata, certificate chains, bundle hashes); expose audit APIs. +- **Phase 4 – Observability & resilience** + Complete telemetry, throttling dashboards, audit trails, fallback key rotation, and offline kit packaging. + +## Work breakdown +- **Authentication & entitlement** + - Enforce Authority-issued DPoP/mTLS tokens with `signer.sign` scope and tenant checks. + - Integrate PoE introspection (cloud licensing) and plan quotas. + - Validate scanner release signature via OCI referrers before signing reports/SBOMs. +- **Signing pipeline** + - Implement DSSE canonicalisation, keyless (Fulcio) and keyful (KMS/HSM/FIDO2) signing. + - Support multi-signature output, certificate chain embedding, and deterministic bundle hashing. + - Provide policy metadata (policy digest, view set) for report predicates. +- **Integrations** + - Coordinate with Attestor on bundle schema, signer identity payload, and error codes. + - Expose Export Center-ready signing API (`/sign/export`) that returns manifest + signature tuple. + - Surface CLI flows (`stella sign sbom/report`, offline verification helpers). +- **Security & key management** + - Key rotation and revocation runbooks; separation of signing keys per tenancy/plan. + - Hardware-backed key support (HSM/FIDO2) with audit logging and attested builds. +- **Observability** + - Metrics: signing latency, PoE failures, quota hits, key usage distribution. + - Structured logs with trace/context IDs, subject digests, issuer mode, decision outcome. + - Alerts for PoE outages, key exhaustion, quota breach, signing failure spikes. +- **Documentation & runbooks** + - Update README/architecture/implementation plan, operator runbooks, offline verification guidance, and CLI reference. + +## Acceptance criteria +- Signer only signs requests that satisfy OpTok, PoE, quota, and scanner provenance checks. +- DSSE outputs (keyless + keyful) verify with standard cosign tooling; Attestor logs them without additional transformation. +- Export Center receives signed bundles, provenance manifests, and signature metadata to package exports deterministically. +- Audit logs capture every signing request with tenant, issuer, subject digest, PoE state, and key source. +- Observability dashboards/alerts reflect latency, failure rate, PoE status, and quota usage. +- CLI/Offline workflows verify signatures using Offline Kit trust roots. + +## Risks & mitigations +- **PoE/entitlement outages:** cache last-known entitlement within TTL, provide emergency bypass toggles with audit trail. +- **Key compromise:** enforce hardware-backed keys, rotation cadence, immediate revocation workflow, incident runbook. +- **Release verification failures:** maintain allowlist for trusted scanner digests, fallback to manual approval with audit. +- **Determinism drift:** canonicalise JSON, lock timestamp sources, regression tests for DSSE hashing. + +## Test strategy +- **Unit:** OpTok/PoE validation, quota enforcement, scanner signature verification, DSSE canonicalisation, multi-sig bundling. +- **Integration:** end-to-end signing for SBOM, report, export artifacts; Attestor ingestion; Export Center bundle signing. +- **Security:** fuzz signing inputs, simulate PoE tampering, ensure unauthorized actors are rejected. +- **Performance:** signing throughput benchmarks (keyless vs keyful), quota pressure, concurrency checks. +- **Offline:** verify signatures using Offline Kit trust roots and cosign CLI without network access. + +## Definition of done +- Signing pipeline deployed with observability and incident runbooks. +- Export Center + Attestor dependencies validated; CLI parity confirmed. +- Documentation updated (README, architecture, runbooks, CLI guides) with imposed rule compliance. +- ./TASKS.md and ../../TASKS.md reflect the latest status transitions. diff --git a/docs/modules/telemetry/AGENTS.md b/docs/modules/telemetry/AGENTS.md new file mode 100644 index 00000000..8d7d9e2c --- /dev/null +++ b/docs/modules/telemetry/AGENTS.md @@ -0,0 +1,22 @@ +# Telemetry agent guide + +## Mission +Telemetry module captures deployment and operations guidance for the shared observability stack (collectors, storage, dashboards). + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/telemetry/README.md b/docs/modules/telemetry/README.md new file mode 100644 index 00000000..6bff4050 --- /dev/null +++ b/docs/modules/telemetry/README.md @@ -0,0 +1,34 @@ +# StellaOps Telemetry + +Telemetry module captures deployment and operations guidance for the shared observability stack (collectors, storage, dashboards). + +## Responsibilities +- Deploy and operate OpenTelemetry collectors for StellaOps services. +- Provide storage configuration for Prometheus/Tempo/Loki stacks. +- Document smoke tests and offline bootstrapping steps. +- Align metrics and alert packs with module SLOs. + +## Key components +- Collector deployment guide (./operations/collector.md). +- Storage deployment guide (./operations/storage.md). +- Smoke tooling in `ops/devops/telemetry/`. + +## Integrations & dependencies +- DevOps pipelines for packaging telemetry bundles. +- Module-specific dashboards (scheduler, scanner, etc.). +- Security/Compliance for retention policies. + +## Operational notes +- Smoke script references (../../ops/devops/telemetry). +- Bundle packaging instructions in ops/devops/telemetry. + +## Related resources +- ./operations/collector.md +- ./operations/storage.md + +## Backlog references +- TELEMETRY-OBS-50-001 … 50-004 in ../../TASKS.md. +- Collector/storage automation tracked in ops/devops/TASKS.md. + +## Epic alignment +- **Epic 15 – Observability & Forensics:** deliver collector/storage deployments, forensic evidence retention, and observability bundles with deterministic configuration. diff --git a/docs/modules/telemetry/TASKS.md b/docs/modules/telemetry/TASKS.md new file mode 100644 index 00000000..b1e7b0cc --- /dev/null +++ b/docs/modules/telemetry/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Telemetry + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| TELEMETRY-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| TELEMETRY-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| TELEMETRY-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/modules/telemetry/architecture.md b/docs/modules/telemetry/architecture.md new file mode 100644 index 00000000..ae098dc7 --- /dev/null +++ b/docs/modules/telemetry/architecture.md @@ -0,0 +1,41 @@ +# Telemetry architecture + +> Derived from Epic 15 – Observability & Forensics; details collector topology, storage profiles, forensic pipelines, and offline packaging. + +## 1) Topology + +- **Collector tier.** OpenTelemetry Collector instances deployed per environment (ingest TLS, GRPC/OTLP receivers, tail-based sampling). Config packages delivered via Offline Kit. +- **Processing pipelines.** Pipelines for traces, metrics, logs with processors (batch, tail sampling, attributes redaction, resource detection). Profiles: `default`, `forensic` (high-retention), `airgap` (file-based exporters). +- **Exporters.** OTLP to Prometheus/Tempo/Loki (online) or file/OTLP-HTTP to Offline Kit staging (air-gapped). Exporters are allow-listed to satisfy Sovereign readiness. + +## 2) Storage + +- **Prometheus** for metrics with remote-write support and retention windows (default 30 days, forensic 180 days). +- **Tempo** (or Jaeger all-in-one) for traces with block storage backend (S3-compatible or filesystem) and deterministic chunk manifests. +- **Loki** for logs stored in immutable chunks; index shards hashed for reproducibility. +- **Forensic archive** — periodic export of raw OTLP records into signed bundles (`otlp/metrics.pb`, `otlp/traces.pb`, `otlp/logs.pb`, `manifest.json`). + +## 3) Pipelines & Guardrails + +- **Redaction.** Attribute processors strip PII/secrets based on policy-managed allowed keys. Redaction profiles mirrored in Offline Kit. +- **Sampling.** Tail sampling by service/error; incident mode (triggered by Orchestrator) promotes services to 100 % sampling, extends retention, and toggles Notify alerts. +- **Alerting.** Prometheus rules/Dashboards packaged with Export Center: service SLOs, queue depth, policy run latency, ingestion AOC violations. + +## 4) APIs & integration + +- `GET /telemetry/config/profile/{name}` — download collector config bundle (YAML + signature). +- `POST /telemetry/incidents/mode` — toggle incident sampling + forensic bundle generation. +- `GET /telemetry/exports/forensic/{window}` — stream signed OTLP bundles for compliance. +- CLI commands: `stella telemetry deploy --profile default`, `stella telemetry capture --window 24h --out bundle.tar.gz`. + +## 5) Offline support + +- Offline Kit ships collector binaries/config, bootstrap scripts, dashboards, alert rules, and OTLP replay tooling. Bundles include `manifest.json` with digests, DSSE signatures, and instructions. +- For offline environments, exporters write to local filesystem; operators transfer bundles to analysis workstation using signed manifests. + +## 6) Observability of telemetry stack + +- Meta-metrics: `collector_export_failures_total`, `telemetry_bundle_generation_seconds`, `telemetry_incident_mode{state}`. +- Health endpoints for collectors and storage clusters, plus dashboards for ingestion rate, retention, rule evaluations. + +Refer to the module README and implementation plan for immediate context, and update this document once component boundaries and data flows are finalised. diff --git a/docs/modules/telemetry/implementation_plan.md b/docs/modules/telemetry/implementation_plan.md new file mode 100644 index 00000000..53d35f51 --- /dev/null +++ b/docs/modules/telemetry/implementation_plan.md @@ -0,0 +1,64 @@ +# Implementation plan — Telemetry + +## Delivery phases +- **Phase 1 – Collector & pipeline profiles** + Publish OpenTelemetry collector configs (`default`, `forensic`, `airgap`), establish ingest gateways, TLS/mTLS, and attribute redaction policies. +- **Phase 2 – Storage backends & retention** + Deploy Prometheus/Tempo/Loki (or equivalents) with retention tiers, bucket/object storage, deterministic manifest generation, and sealed-mode allowlists. +- **Phase 3 – Incident mode & forensic capture** + Implement incident toggles (CLI/API), tail sampling adjustments, forensic bundle generation (OTLP archives, manifest/signature), and Notify hooks. +- **Phase 4 – Observability dashboards & automation** + Deliver dashboards (service SLOs, queue depth, policy latency), alert rules, Grafana packages, and CLI automation for deployment and capture. +- **Phase 5 – Offline & compliance** + Ship Offline Kit artefacts (collectors, configs, dashboards, replay tooling), signed bundles, and documentation for air-gapped review workflows. +- **Phase 6 – Hardening & SOC handoff** + Complete RBAC integration, audit logging, incident response runbooks, performance tuning, and integration tests across services. + +## Work breakdown +- **Collector configs** + - Maintain config templates per profile with processors (redaction, batching, resource detection) and exporters. + - CLI automation (`stella telemetry deploy`, `stella telemetry profile diff`), validation tests, and config signing. +- **Storage & retention** + - Provision Prometheus/Tempo/Loki (or vendor equivalents) with retention tiers (default, forensic, airgap). + - Ensure determinism (chunk manifests, content hashing), remote-write allowlists, sealed/offline modes. + - Implement archivers for forensic bundles (metrics/traces/logs) with cosign signatures. +- **Incident mode** + - API/CLI to toggle incident sampling, retention escalation, Notify signals, and auto bundle capture. + - Hook into Orchestrator to respond to incidents and revert after cooldown. +- **Dashboards & alerts** + - Dashboard packages for core services (ingestion, policy, export, attestation). + - Alert rules for SLO burn, collector failure, exporter backlog, bundle generation errors. + - Self-observability metrics (`collector_export_failures_total`, `telemetry_incident_mode{}`). +- **Offline support** + - Offline Kit assets: collector binaries/configs, import scripts, dashboards, replay instructions, compliance checklists. + - File-based exporters and manual transfer workflows with signed manifests. +- **Docs & runbooks** + - Update observability overview, forensic capture guide, incident response checklist, sealed-mode instructions, RBAC matrix. + - SOC handoff package with control objectives and audit evidence. + +## Acceptance criteria +- Collectors ingest metrics/logs/traces across deployments, applying redaction rules and tenant isolation; profiles validate via CI. +- Storage backends retain data per default/forensic/airgap SLAs with deterministic chunk manifests and sealed-mode compliance. +- Incident mode toggles sampling to 100 %, extends retention, triggers Notify, and captures forensic bundles signed with cosign. +- Dashboards and alerts cover service SLOs, queue depth, policy latency, ingestion violations, and telemetry stack health. +- CLI commands (`stella telemetry deploy/capture/status`) automate config rollout, forensic capture, and verification. +- Offline bundles replay telemetry in sealed environments using provided scripts and manifests. + +## Risks & mitigations +- **PII leakage:** strict redaction processors, policy-managed allowlists, audit tests. +- **Collector overload:** horizontal scaling, batching, circuit breakers, incident mode throttling. +- **Storage cost:** tiered retention, compression, pruning policies, offline archiving. +- **Air-gap drift:** offline kit refresh schedule, deterministic manifest verification. +- **Alert fatigue:** burn-rate alerts, deduping, SOC runbooks. + +## Test strategy +- **Config lint/tests:** schema validation, unit tests for processors/exporters, golden configs. +- **Integration:** simulate service traces/logs/metrics, verify pipelines, incident toggles, bundle generation. +- **Performance:** load tests with peak ingestion, long retention windows, failover scenarios. +- **Security:** redaction verification, RBAC/tenant scoping, sealed-mode tests, signed config verification. +- **Offline:** capture bundles, transfer, replay, compliance attestation. + +## Definition of done +- Collector profiles, storage backends, incident mode, dashboards, CLI, and offline kit delivered with telemetry and documentation. +- Runbooks and SOC handoff packages published; compliance checklists appended. +- ./TASKS.md and ../../TASKS.md updated; imposed rule statements confirmed in documentation. diff --git a/docs/ops/telemetry-collector.md b/docs/modules/telemetry/operations/collector.md similarity index 97% rename from docs/ops/telemetry-collector.md rename to docs/modules/telemetry/operations/collector.md index c6915bb9..588115f6 100644 --- a/docs/ops/telemetry-collector.md +++ b/docs/modules/telemetry/operations/collector.md @@ -1,113 +1,113 @@ -# Telemetry Collector Deployment Guide - -> **Scope:** DevOps Guild, Observability Guild, and operators enabling the StellaOps telemetry pipeline (DEVOPS-OBS-50-001 / DEVOPS-OBS-50-003). - -This guide describes how to deploy the default OpenTelemetry Collector packaged with Stella Ops, validate its ingest endpoints, and prepare an offline-ready bundle for air-gapped environments. - ---- - -## 1. Overview - -The collector terminates OTLP traffic from Stella Ops services and exports metrics, traces, and logs. - -| Endpoint | Purpose | TLS | Authentication | -| -------- | ------- | --- | -------------- | -| `:4317` | OTLP gRPC ingest | mTLS | Client certificate issued by collector CA | -| `:4318` | OTLP HTTP ingest | mTLS | Client certificate issued by collector CA | -| `:9464` | Prometheus scrape | mTLS | Same client certificate | -| `:13133` | Health check | mTLS | Same client certificate | -| `:1777` | pprof diagnostics | mTLS | Same client certificate | - -The default configuration lives at `deploy/telemetry/otel-collector-config.yaml` and mirrors the Helm values in the `stellaops` chart. - ---- - -## 2. Local validation (Compose) - -```bash -# 1. Generate dev certificates (CA + collector + client) -./ops/devops/telemetry/generate_dev_tls.sh - -# 2. Start the collector overlay -cd deploy/compose -docker compose -f docker-compose.telemetry.yaml up -d - -# 3. Start the storage overlay (Prometheus, Tempo, Loki) -docker compose -f docker-compose.telemetry-storage.yaml up -d - -# 4. Run the smoke test (OTLP HTTP) -python ../../ops/devops/telemetry/smoke_otel_collector.py --host localhost -``` - -The smoke test posts sample traces, metrics, and logs and verifies that the collector increments the `otelcol_receiver_accepted_*` counters exposed via the Prometheus exporter. The storage overlay gives you a local Prometheus/Tempo/Loki stack to confirm end-to-end wiring. The same client certificate can be used by local services to weave traces together. See [`Telemetry Storage Deployment`](telemetry-storage.md) for the storage configuration guidelines used in staging/production. - ---- - -## 3. Kubernetes deployment - -Enable the collector in Helm by setting the following values (example shown for the dev profile): - -```yaml -telemetry: - collector: - enabled: true - defaultTenant: - tls: - secretName: stellaops-otel-tls- -``` - -Provide a Kubernetes secret named `stellaops-otel-tls-` (for staging: `stellaops-otel-tls-stage`) with the keys `tls.crt`, `tls.key`, and `ca.crt`. The secret must contain the collector certificate, private key, and issuing CA respectively. Example: - -```bash -kubectl create secret generic stellaops-otel-tls-stage \ - --from-file=tls.crt=collector.crt \ - --from-file=tls.key=collector.key \ - --from-file=ca.crt=ca.crt -``` - -Helm renders the collector deployment, service, and config map automatically: - -```bash -helm upgrade --install stellaops deploy/helm/stellaops -f deploy/helm/stellaops/values-dev.yaml -``` - -Update client workloads to trust `ca.crt` and present client certificates that chain back to the same CA. - ---- - -## 4. Offline packaging (DEVOPS-OBS-50-003) - -Use the packaging helper to produce a tarball that can be mirrored inside the Offline Kit or air-gapped sites: - -```bash -python ops/devops/telemetry/package_offline_bundle.py --output out/telemetry/telemetry-bundle.tar.gz -``` - -The script gathers: - -- `deploy/telemetry/README.md` -- Collector configuration (`deploy/telemetry/otel-collector-config.yaml` and Helm copy) -- Helm template/values for the collector -- Compose overlay (`deploy/compose/docker-compose.telemetry.yaml`) - -The tarball ships with a `.sha256` checksum. To attach a Cosign signature, add `--sign` and provide `COSIGN_KEY_REF`/`COSIGN_IDENTITY_TOKEN` env vars (or use the `--cosign-key` flag). - -Distribute the bundle alongside certificates generated by your PKI. For air-gapped installs, regenerate certificates inside the enclave and recreate the `stellaops-otel-tls` secret. - ---- - -## 5. Operational checks - -1. **Health probes** – `kubectl exec` into the collector pod and run `curl -fsSk --cert client.crt --key client.key --cacert ca.crt https://127.0.0.1:13133/healthz`. -2. **Metrics scrape** – confirm Prometheus ingests `otelcol_receiver_accepted_*` counters. -3. **Trace correlation** – ensure services propagate `trace_id` and `tenant.id` attributes; refer to `docs/observability/observability.md` for expected spans. -4. **Certificate rotation** – when rotating the CA, update the secret and restart the collector; roll out new client certificates before enabling `require_client_certificate` if staged. - ---- - -## 6. Related references - -- `deploy/telemetry/README.md` – source configuration and local workflow. -- `ops/devops/telemetry/smoke_otel_collector.py` – OTLP smoke test. -- `docs/observability/observability.md` – metrics/traces/logs taxonomy. -- `docs/13_RELEASE_ENGINEERING_PLAYBOOK.md` – release checklist for telemetry assets. +# Telemetry Collector Deployment Guide + +> **Scope:** DevOps Guild, Observability Guild, and operators enabling the StellaOps telemetry pipeline (DEVOPS-OBS-50-001 / DEVOPS-OBS-50-003). + +This guide describes how to deploy the default OpenTelemetry Collector packaged with Stella Ops, validate its ingest endpoints, and prepare an offline-ready bundle for air-gapped environments. + +--- + +## 1. Overview + +The collector terminates OTLP traffic from Stella Ops services and exports metrics, traces, and logs. + +| Endpoint | Purpose | TLS | Authentication | +| -------- | ------- | --- | -------------- | +| `:4317` | OTLP gRPC ingest | mTLS | Client certificate issued by collector CA | +| `:4318` | OTLP HTTP ingest | mTLS | Client certificate issued by collector CA | +| `:9464` | Prometheus scrape | mTLS | Same client certificate | +| `:13133` | Health check | mTLS | Same client certificate | +| `:1777` | pprof diagnostics | mTLS | Same client certificate | + +The default configuration lives at `deploy/telemetry/otel-collector-config.yaml` and mirrors the Helm values in the `stellaops` chart. + +--- + +## 2. Local validation (Compose) + +```bash +# 1. Generate dev certificates (CA + collector + client) +./ops/devops/telemetry/generate_dev_tls.sh + +# 2. Start the collector overlay +cd deploy/compose +docker compose -f docker-compose.telemetry.yaml up -d + +# 3. Start the storage overlay (Prometheus, Tempo, Loki) +docker compose -f docker-compose.telemetry-storage.yaml up -d + +# 4. Run the smoke test (OTLP HTTP) +python ../../ops/devops/telemetry/smoke_otel_collector.py --host localhost +``` + +The smoke test posts sample traces, metrics, and logs and verifies that the collector increments the `otelcol_receiver_accepted_*` counters exposed via the Prometheus exporter. The storage overlay gives you a local Prometheus/Tempo/Loki stack to confirm end-to-end wiring. The same client certificate can be used by local services to weave traces together. See [`Telemetry Storage Deployment`](telemetry-storage.md) for the storage configuration guidelines used in staging/production. + +--- + +## 3. Kubernetes deployment + +Enable the collector in Helm by setting the following values (example shown for the dev profile): + +```yaml +telemetry: + collector: + enabled: true + defaultTenant: + tls: + secretName: stellaops-otel-tls- +``` + +Provide a Kubernetes secret named `stellaops-otel-tls-` (for staging: `stellaops-otel-tls-stage`) with the keys `tls.crt`, `tls.key`, and `ca.crt`. The secret must contain the collector certificate, private key, and issuing CA respectively. Example: + +```bash +kubectl create secret generic stellaops-otel-tls-stage \ + --from-file=tls.crt=collector.crt \ + --from-file=tls.key=collector.key \ + --from-file=ca.crt=ca.crt +``` + +Helm renders the collector deployment, service, and config map automatically: + +```bash +helm upgrade --install stellaops deploy/helm/stellaops -f deploy/helm/stellaops/values-dev.yaml +``` + +Update client workloads to trust `ca.crt` and present client certificates that chain back to the same CA. + +--- + +## 4. Offline packaging (DEVOPS-OBS-50-003) + +Use the packaging helper to produce a tarball that can be mirrored inside the Offline Kit or air-gapped sites: + +```bash +python ops/devops/telemetry/package_offline_bundle.py --output out/telemetry/telemetry-bundle.tar.gz +``` + +The script gathers: + +- `deploy/telemetry/README.md` +- Collector configuration (`deploy/telemetry/otel-collector-config.yaml` and Helm copy) +- Helm template/values for the collector +- Compose overlay (`deploy/compose/docker-compose.telemetry.yaml`) + +The tarball ships with a `.sha256` checksum. To attach a Cosign signature, add `--sign` and provide `COSIGN_KEY_REF`/`COSIGN_IDENTITY_TOKEN` env vars (or use the `--cosign-key` flag). + +Distribute the bundle alongside certificates generated by your PKI. For air-gapped installs, regenerate certificates inside the enclave and recreate the `stellaops-otel-tls` secret. + +--- + +## 5. Operational checks + +1. **Health probes** – `kubectl exec` into the collector pod and run `curl -fsSk --cert client.crt --key client.key --cacert ca.crt https://127.0.0.1:13133/healthz`. +2. **Metrics scrape** – confirm Prometheus ingests `otelcol_receiver_accepted_*` counters. +3. **Trace correlation** – ensure services propagate `trace_id` and `tenant.id` attributes; refer to `docs/observability/observability.md` for expected spans. +4. **Certificate rotation** – when rotating the CA, update the secret and restart the collector; roll out new client certificates before enabling `require_client_certificate` if staged. + +--- + +## 6. Related references + +- `deploy/telemetry/README.md` – source configuration and local workflow. +- `ops/devops/telemetry/smoke_otel_collector.py` – OTLP smoke test. +- `docs/observability/observability.md` – metrics/traces/logs taxonomy. +- `docs/13_RELEASE_ENGINEERING_PLAYBOOK.md` – release checklist for telemetry assets. diff --git a/docs/ops/telemetry-storage.md b/docs/modules/telemetry/operations/storage.md similarity index 97% rename from docs/ops/telemetry-storage.md rename to docs/modules/telemetry/operations/storage.md index 8f1139ab..f2a3ca6a 100644 --- a/docs/ops/telemetry-storage.md +++ b/docs/modules/telemetry/operations/storage.md @@ -161,7 +161,7 @@ Provision the following secrets/configs (names can be overridden via Helm values - [ ] Tempo and Loki report tenant activity (`/api/status`). - [ ] Retention policy tested by uploading sample data and verifying expiry. - [ ] Alerts wired into SLO evaluator (DEVOPS-OBS-51-001). -- [ ] Component rule packs imported (e.g. `docs/ops/scheduler-worker-prometheus-rules.yaml`). +- [ ] Component rule packs imported (e.g. `docs/modules/scheduler/operations/worker-prometheus-rules.yaml`). --- @@ -169,5 +169,5 @@ Provision the following secrets/configs (names can be overridden via Helm values - `deploy/telemetry/storage/README.md` - `deploy/compose/docker-compose.telemetry-storage.yaml` -- `docs/ops/telemetry-collector.md` +- `docs/modules/telemetry/operations/collector.md` - `docs/observability/observability.md` diff --git a/docs/modules/ui/AGENTS.md b/docs/modules/ui/AGENTS.md new file mode 100644 index 00000000..397addab --- /dev/null +++ b/docs/modules/ui/AGENTS.md @@ -0,0 +1,22 @@ +# Console UI agent guide + +## Mission +The Console presents operator dashboards for scans, policies, VEX evidence, runtime posture, and admin workflows. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/ui/README.md b/docs/modules/ui/README.md new file mode 100644 index 00000000..c7fb5348 --- /dev/null +++ b/docs/modules/ui/README.md @@ -0,0 +1,41 @@ +# StellaOps Console UI + +The Console presents operator dashboards for scans, policies, VEX evidence, runtime posture, and admin workflows. + +## Responsibilities +- Render real-time status for ingestion, scanning, policy, and exports via SSE. +- Provide policy editor, SBOM explorer, and advisory views with accessibility compliance. +- Integrate with Authority for fresh-auth and scope enforcement. +- Support offline bundles with deterministic build outputs. + +## Key components +- Angular 17 workspace under `src/UI/StellaOps.UI`. +- Signals-based state management with `@ngrx/signals` store. +- API client generator (`core/api`). + +## Integrations & dependencies +- Backend APIs (Scanner, Policy, Notify, Export Center, Attestor). +- Authority for DPoP-protected calls. +- Telemetry streams for observability dashboards. + +## Operational notes +- Auth smoke tests in ./operations/auth-smoke.md. +- Console architecture doc for layout and SSE fan-out. +- Accessibility and security guides in ../../ui/ & ../../security/. + +## Related resources +- ./operations/auth-smoke.md +- ./console-architecture.md + +## Backlog references +- DOCS-CONSOLE-23-001 … DOCS-CONSOLE-23-003 baseline (done). +- CONSOLE-OBS-52-001 tasks for observability updates. + +## Epic alignment +- **Epic 2 – Policy Engine & Editor:** deliver deterministic policy authoring, simulation, and explain UX. +- **Epic 4 – Policy Studio:** implement registry workspace, approvals, and promotion workflows. +- **Epic 5 – SBOM Graph Explorer:** surface graph navigation, overlays, and diff tools. +- **Epic 6 – Vulnerability Explorer:** provide triage dashboards, findings ledger views, and audit exports. +- **Epic 8 – Advisory AI:** embed advisory summaries, explanations, and remediation hints with citations. +- **Epic 9 – Orchestrator Dashboard:** expose source/job monitoring with throttling and replay controls. +- **Epic 11 – Notifications Studio:** deliver notifications workspace with rule/channel previews and audits. diff --git a/docs/modules/ui/TASKS.md b/docs/modules/ui/TASKS.md new file mode 100644 index 00000000..c24d21a8 --- /dev/null +++ b/docs/modules/ui/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Console UI + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| CONSOLE UI-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| CONSOLE UI-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| CONSOLE UI-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_UI.md b/docs/modules/ui/architecture.md similarity index 98% rename from docs/ARCHITECTURE_UI.md rename to docs/modules/ui/architecture.md index 58c9c373..eba29210 100644 --- a/docs/ARCHITECTURE_UI.md +++ b/docs/modules/ui/architecture.md @@ -1,5 +1,7 @@ # component_architecture_web_ui.md — **Stella Ops Web UI** (2025Q4) +> Consolidates Console requirements documented across the Policy, Graph, Vulnerability Explorer, Advisory AI, Orchestrator, and Notifications module guides and implementation plans. + > **Scope.** Implementation‑ready architecture for the **Angular SPA** that operators and developers use to drive Stella Ops. This document defines UX surfaces, module boundaries, data flows, auth, RBAC, real‑time updates, performance targets, i18n/a11y, security headers, testing and deployment. The UI is a *consumer* of backend APIs (Scanner, Policy, Excititor, Concelier, Attestor, Authority) and never performs scanning, merging, or signing on its own. --- diff --git a/docs/architecture/console.md b/docs/modules/ui/console-architecture.md similarity index 94% rename from docs/architecture/console.md rename to docs/modules/ui/console-architecture.md index 2c14a59b..32cf3eed 100644 --- a/docs/architecture/console.md +++ b/docs/modules/ui/console-architecture.md @@ -1,8 +1,10 @@ # StellaOps Console Architecture (Sprint 23) +> Maps the Console implementation to the requirements captured in the Policy, Graph, Vulnerability Explorer, Orchestrator, and Notifications module documentation set. + > **Ownership:** Console Guild • Docs Guild > **Delivery scope:** `StellaOps.Web` Angular workspace, Console Web Gateway routes (`/console/*`), Downloads manifest surfacing, SSE fan-out for Scheduler & telemetry. -> **Related docs:** [Console overview](../ui/console-overview.md), [Navigation](../ui/navigation.md), [Runs workspace](../ui/runs.md), [Downloads](../ui/downloads.md), [Console security posture](../security/console-security.md), [Console observability](../observability/ui-telemetry.md), [Deployment guide](../deploy/console.md) +> **Related docs:** [Console overview](../../ui/console-overview.md), [Navigation](../../ui/navigation.md), [Runs workspace](../../ui/runs.md), [Downloads](../../ui/downloads.md), [Console security posture](../../security/console-security.md), [Console observability](../../observability/ui-telemetry.md), [Deployment guide](../../deploy/console.md) This dossier describes the end-to-end architecture of the StellaOps Console as delivered in Sprint 23. It covers the Angular workspace layout, API/gateway integration points, live-update channels, performance budgets, offline workflows, and observability hooks needed to keep the console deterministic and air-gap friendly. @@ -162,13 +164,13 @@ Optimisation levers: - **Tenant propagation:** `X-Stella-Tenant` header derived from token; downstream services reject mismatches. Tenant switches log `ui.tenant.switch` and require fresh-auth for privileged actions. - **CSP & headers:** Default CSP forbids third-party scripts, only allows same-origin `connect-src`. HSTS, Referrer-Policy `no-referrer`, and `Permissions-Policy` configured via gateway (`deploy/console.md`). - **Evidence handling:** Downloads never cache secrets; UI renders SHA-256 + signature references and steers users to CLI for sensitive exports. -- See [Console security posture](../security/console-security.md) for full scope table and threat model alignment. +- See [Console security posture](../../security/console-security.md) for full scope table and threat model alignment. --- ## 8 · Observability & Telemetry -- **Metrics:** Prometheus scrape at `/metrics` (enabled when `CONSOLE_METRICS_ENABLED=true`). Key histograms/counters documented in [Console observability](../observability/ui-telemetry.md) (`ui_route_render_seconds`, `ui_tenant_switch_total`, `ui_download_manifest_refresh_seconds`). +- **Metrics:** Prometheus scrape at `/metrics` (enabled when `CONSOLE_METRICS_ENABLED=true`). Key histograms/counters documented in [Console observability](../../observability/ui-telemetry.md) (`ui_route_render_seconds`, `ui_tenant_switch_total`, `ui_download_manifest_refresh_seconds`). - **Logs:** Structured JSON with `traceId`, `tenant`, `action`. Categories include `ui.action`, `ui.tenant.switch`, `ui.security.anomaly`. Sampled per feature flag to balance volume. - **Traces:** Browser OTLP exporter ships spans to configured collector; gateway adds server-side spans so traces cross client/server boundary. - **Alerts:** Burn-rate rules for route latency, telemetry batch failures, download manifest refresh, and SSE stalls integrate with Notifier. @@ -207,4 +209,3 @@ Optimisation levers: --- *Last updated: 2025-10-27 (Sprint 23).* - diff --git a/docs/modules/ui/implementation_plan.md b/docs/modules/ui/implementation_plan.md new file mode 100644 index 00000000..308409de --- /dev/null +++ b/docs/modules/ui/implementation_plan.md @@ -0,0 +1,25 @@ +# Implementation plan — Console UI + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Epic milestones +- **Epic 2 – Policy Engine & Editor:** deliver policy editor simulation and explain UX. +- **Epic 4 – Policy Studio:** build registry, approvals, and promotion experiences. +- **Epic 5 – SBOM Graph Explorer:** implement graph navigation, overlays, and diff views. +- **Epic 6 – Vulnerability Explorer:** surface triage dashboards, findings ledger, and audit exports. +- **Epic 8 – Advisory AI:** integrate advisory summaries and remediation hints with strict provenance. +- **Epic 9 – Orchestrator Dashboard:** expose job/source monitoring controls. +- **Epic 11 – Notifications Studio:** provide notifications workspace with previews and audit trails. +- Track supporting tasks (e.g., DOCS-CONSOLE-23-001, CONSOLE-OBS-52-001) in ../../TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ops/ui-auth-smoke.md b/docs/modules/ui/operations/auth-smoke.md similarity index 100% rename from docs/ops/ui-auth-smoke.md rename to docs/modules/ui/operations/auth-smoke.md diff --git a/docs/modules/vex-lens/AGENTS.md b/docs/modules/vex-lens/AGENTS.md new file mode 100644 index 00000000..5919a187 --- /dev/null +++ b/docs/modules/vex-lens/AGENTS.md @@ -0,0 +1,22 @@ +# VEX Consensus Lens agent guide + +## Mission +VEX Lens computes deterministic consensus across conflicting VEX statements while preserving raw provenance. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Review ./architecture.md for consensus algorithm, trust model, and export contracts. +2. Open ../../implplan/SPRINTS.md and locate stories for this component. +3. Check ./TASKS.md and update status before/after work. +4. Read README/architecture for design context and update as the implementation evolves. + +## Guardrails +- Uphold Aggregation-Only Contract boundaries when consuming ingestion data. +- Preserve determinism and provenance in all derived outputs. +- Document offline/air-gap pathways for any new feature. +- Update telemetry/observability assets alongside feature work. diff --git a/docs/modules/vex-lens/README.md b/docs/modules/vex-lens/README.md new file mode 100644 index 00000000..74fb6e53 --- /dev/null +++ b/docs/modules/vex-lens/README.md @@ -0,0 +1,28 @@ +# StellaOps VEX Consensus Lens + +VEX Lens computes deterministic consensus across conflicting VEX statements while preserving raw provenance. + +## Responsibilities +- Ingest VEX evidence from Excititor and align it to SBOM inventory. +- Apply issuer trust weights, freshness rules, and policy-defined tie breakers. +- Publish consensus snapshots and disagreement metadata for Policy Engine and Explorer surfaces. +- Expose APIs for explainability and offline bundle exports. + +## Key components +- Consensus computation service and job pipeline. +- Consensus store with versioned snapshots. +- Explain trace generator for disagreements. + +## Integrations & dependencies +- Excititor for raw VEX ingestion. +- Policy Engine for applying consensus in suppression flows. +- Vulnerability Explorer and Advisory AI for evidence overlays. + +## Operational notes +- Trust model configuration and issuer scoring dashboards. +- Offline kit packaging of consensus snapshots. +- Telemetry on issuer coverage and disagreement counts. + +## Epic alignment +- Epic 7: VEX Consensus Lens. +- Lens implementation stories tracked in ../../TASKS.md. diff --git a/docs/modules/vex-lens/TASKS.md b/docs/modules/vex-lens/TASKS.md new file mode 100644 index 00000000..4bffe403 --- /dev/null +++ b/docs/modules/vex-lens/TASKS.md @@ -0,0 +1,9 @@ +# Task board — VEX Consensus Lens + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| VEX-CONSENSUS-LENS-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Ensure ./README.md reflects the latest epic deliverables. | Align with ./AGENTS.md | +| VEX-CONSENSUS-LENS-ENG-0001 | TODO | Module Team | Break down epic milestones into actionable stories. | Sync into ../../TASKS.md | +| VEX-CONSENSUS-LENS-OPS-0001 | TODO | Ops Guild | Prepare runbooks/observability assets once MVP lands. | Document outputs in ./README.md | diff --git a/docs/modules/vex-lens/architecture.md b/docs/modules/vex-lens/architecture.md new file mode 100644 index 00000000..75c6a0a1 --- /dev/null +++ b/docs/modules/vex-lens/architecture.md @@ -0,0 +1,69 @@ +# VEX Consensus Lens architecture + +> Based on Epic 7 – VEX Consensus Lens; consolidates trust modelling, consensus computation, and API contracts. + +## 1) Purpose + +Compute a deterministic, reproducible consensus view over multiple VEX statements for each `(artifact, advisory)` tuple while preserving conflicts and provenance. Output is consumed by Policy Engine, Vulnerability Explorer, Advisory AI, and Console overlays. + +## 2) Inputs + +- `vex_normalized` tuples emitted by Excititor (status, justification, scope, timestamp, content hash). +- Issuer trust registry (`vex_issuer_registry`) providing trust tier, confidence, authority scope. +- Optional runtime context (Zastava exposure) and policy precedence rules. + +## 3) Core algorithm + +1. Group tuples by `(artifactId, advisoryKey)`. +2. Sort statements by `timestamp` then trust tier (critical → low) then confidence. +3. Apply lattice join: + - States: `unknown < under_investigation < not_affected | affected < fixed`. + - Conflicts triggered when competing issuers disagree at the same precedence level. +4. Generate consensus record with fields: + ```json + { + "artifact": "pkg:rpm/redhat/openssl@3.0.9", + "advisory": "CVE-2025-13579", + "status": "not_affected", + "confidence": 0.92, + "derived_from": ["vex_raw:openvex:VEX-2025-00001:v2", "vex_raw:csaf:RHSA-2025:1234:v1"], + "conflicts": [{"issuer":"vendor:upstream","status":"affected"}], + "issued_at": "2025-08-30T12:05:00Z", + "consensus_digest": "sha256:..." + } + ``` +5. Persist consensus and emit `vex.consensus.updated` DSSE event. + +Conflicts remain visible through `conflicts` array; Policy Engine can decide suppression strategy based on trust weights. + +## 4) APIs + +- `GET /v1/vex/consensus?artifact=...&advisory=...` — returns consensus record and conflict list. +- `GET /v1/vex/conflicts` — list outstanding conflicts with severity, trust delta, and time since disagreement. +- `POST /v1/vex/trust/weights` — (admin) update trust tiers/confidence (requires Authority scopes); updates propagate to recomputation jobs. +- `GET /v1/vex/consensus/export` — stream deterministic JSONL for Offline Kit / Export Center mirror bundles. + +All responses include provenance fields (`consensus_digest`, `derived_from`, DSSE signature references) for audit. + +## 5) Storage + +- `vex_consensus` collection keyed by `(tenant, artifactId, advisoryKey)` with current consensus, metadata, conflict summary, and digests. +- `vex_consensus_history` append-only history to support replay and audit. +- `vex_conflict_queue` for unresolved conflicts requiring manual review. + +## 6) Recompute strategy + +- Incremental updates triggered by Excititor deltas, trust registry changes, or policy precedence updates. +- Recompute jobs run via Orchestrator; deterministic ordering ensures identical results for the same input set. +- Jobs produce SRM-style manifests for recomputation verification. + +## 7) Observability + +- Metrics: `vex_consensus_conflicts_total`, `vex_consensus_latency_seconds`, `vex_consensus_recompute_seconds{reason}`. +- Logs: include `artifactId`, `advisoryKey`, `issuer`, `status`, `trustTier`. +- Traces: `consensus.group`, `consensus.join`, `consensus.persist` spans. + +## 8) Offline & export + +- Bundle format: `consensus.jsonl`, `conflicts.jsonl`, `manifest.json`, `signatures/`. Each record references raw statement digests and trust metadata. +- Export Center uses the bundle for mirror profiles; CLI supports `stella vex consensus export` mirroring the API. diff --git a/docs/modules/vex-lens/implementation_plan.md b/docs/modules/vex-lens/implementation_plan.md new file mode 100644 index 00000000..8958d158 --- /dev/null +++ b/docs/modules/vex-lens/implementation_plan.md @@ -0,0 +1,63 @@ +# Implementation plan — VEX Consensus Lens + +## Delivery phases +- **Phase 1 – Core lens service** + Build normalisation pipeline (CSAF/OpenVEX/CycloneDX), product mapping library, trust weighting functions, consensus algorithm, and persistence (`vex_consensus`, history, conflicts). +- **Phase 2 – API & integrations** + Expose `/vex/consensus` query/detail/simulate/export endpoints, integrate Policy Engine thresholds, Vuln Explorer UI chips, and VEX Lens change events. +- **Phase 3 – Issuer Directory & signatures** + Deliver issuer registry, key management, signature verification, RBAC, audit logs, and tenant overrides. +- **Phase 4 – Console & CLI experiences** + Ship Console module (lists, evidence table, quorum bar, conflicts, simulation drawer) and CLI commands (`stella vex consensus ...`) with export support. +- **Phase 5 – Recompute & performance** + Implement recompute scheduling (policy activation, Excitator deltas), caching, load tests (10M records/tenant), observability dashboards, and Offline Kit exports. + +## Work breakdown +- **VEX Lens service** + - Normalise VEX payloads, maintain scope scores, compute consensus digest. + - Trust weighting functions (issuer tier, freshness decay, scope quality). + - Idempotent workers for consensus projection and history tracking. + - Conflict handling queue for manual review and notifications. +- **Integrations** + - Excitator: enrich VEX events with issuer hints, signatures, product trees. + - Policy Engine: trust knobs, simulation endpoints, policy-driven recompute. + - Vuln Explorer & Advisory AI: consensus badges, conflict surfacing. +- **Issuer Directory** + - CRUD for issuers/keys, audit logs, import CSAF publishers, tenant overrides. + - Signature verification endpoints consumed by Lens. +- **APIs & UX** + - REST endpoints for query/detail/conflict export, trust weight updates. + - Console module with filters, saved views, evidence table, simulation drawer. + - CLI commands for list/show/simulate/export with JSON/CSV output. +- **Observability & Ops** + - Metrics (consensus latency, conflict rate, signature failures, cache hit rate), logs, traces. + - Dashboards + runbooks for recompute storms, mapping failures, signature errors, quota breaches. + - Offline exports for Export Center/Offline Kit. + +## Acceptance criteria +- Consensus results reproducible across supported VEX formats with deterministic digests and provenance. +- Signature verification influences trust weights; unverifiable evidence is down-weighted without pipeline failure. +- Policy simulations show quorum shifts without persisting state; Vuln Explorer consumes consensus signals. +- Issuer Directory enforces RBAC, audit logs, and key rotation; CLI & Console parity achieved. +- Recompute pipeline handles Excitator deltas and policy activations with backpressure and incident surfacing. +- Observability dashboards/alerts cover ingestion lag, conflict spikes, signature failures, performance budgets (P95 < 500 ms for 100-row pages at 10M records/tenant). + +## Risks & mitigations +- **Product mapping ambiguity:** conservative scope scoring, manual overrides, surfaced warnings, policy review hooks. +- **Issuer compromise:** signature verification, trust weighting, tenant overrides, revocation runbooks. +- **Evidence storms:** batching, worker sharding, orchestrator rate limiting, priority queues. +- **Performance degradation:** caching, indexing, load tests, quota enforcement. +- **Offline gaps:** deterministic exports, manifest hashes, Offline Kit tests. + +## Test strategy +- **Unit:** normalisers, mapping, trust weights, consensus lattice, signature verification. +- **Property:** randomised evidence sets verifying lattice commutativity and determinism. +- **Integration:** Excitator → Lens → Policy/Vuln Explorer flow, issuer overrides, simulation. +- **Performance:** large tenant datasets, cache behaviour, concurrency tests. +- **Security:** RBAC, tenant scoping, signature tampering, issuer revocation. +- **Offline:** export/import verification, CLI parity. + +## Definition of done +- Lens service, issuer directory, API/CLI/Console components deployed with telemetry and runbooks. +- Documentation set (overview, algorithm, issuer directory, API, console, policy trust) updated with imposed rule statements. +- ./TASKS.md and ../../TASKS.md reflect current status; Offline Kit parity confirmed. diff --git a/docs/modules/vexer/AGENTS.md b/docs/modules/vexer/AGENTS.md new file mode 100644 index 00000000..c9934d72 --- /dev/null +++ b/docs/modules/vexer/AGENTS.md @@ -0,0 +1,22 @@ +# Vexer agent guide + +## Mission +Vexer computes deterministic consensus across VEX claims, preserving conflicts and producing attestable evidence for policy suppression. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/vexer/README.md b/docs/modules/vexer/README.md new file mode 100644 index 00000000..05fdc8b5 --- /dev/null +++ b/docs/modules/vexer/README.md @@ -0,0 +1,34 @@ +# StellaOps Vexer + +Vexer computes deterministic consensus across VEX claims, preserving conflicts and producing attestable evidence for policy suppression. + +## Responsibilities +- Ingest Excititor observations and compute per-product consensus snapshots. +- Provide APIs for querying canonical VEX positions and conflict sets. +- Publish exports and DSSE-ready digests for downstream consumption. +- Keep provenance weights and disagreement metadata. + +## Key components +- Consensus engine and API host in `StellaOps.Vexer.*` (to-be-implemented). +- Storage schema for consensus graphs. +- Integration hooks for Policy Engine suppression logic. + +## Integrations & dependencies +- Excititor for raw observations. +- Policy Engine and UI for suppression stories. +- CLI for evidence inspection. + +## Operational notes +- Deterministic consensus algorithms (see architecture). +- Planned telemetry for disagreement counts and freshness. +- Offline exports aligning with Concelier/Excititor timelines. + +## Related resources +- ./scoring.md + +## Backlog references +- DOCS-VEXER backlog referenced in architecture doc. +- CLI parity tracked in ../../TASKS.md (CLI-GRAPH/VEX stories). + +## Epic alignment +- **Epic 7 – VEX Consensus Lens:** deliver trust-weighted consensus snapshots, disagreement metadata, and explain APIs. diff --git a/docs/modules/vexer/TASKS.md b/docs/modules/vexer/TASKS.md new file mode 100644 index 00000000..3f3769eb --- /dev/null +++ b/docs/modules/vexer/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Vexer + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| VEXER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| VEXER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| VEXER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_VEXER.md b/docs/modules/vexer/architecture.md similarity index 97% rename from docs/ARCHITECTURE_VEXER.md rename to docs/modules/vexer/architecture.md index 7722fb19..e12e864f 100644 --- a/docs/ARCHITECTURE_VEXER.md +++ b/docs/modules/vexer/architecture.md @@ -1,4 +1,6 @@ -# component_architecture_vexer.md — **Stella Ops Vexer** (2025Q4) +# component_architecture_vexer.md — **Stella Ops Vexer** (2025Q4) + +> Built to satisfy Epic 7 – VEX Consensus Lens requirements. > **Scope.** This document specifies the **Vexer** service: its purpose, trust model, data structures, APIs, plug‑in contracts, storage schema, normalization/consensus algorithms, performance budgets, testing matrix, and how it integrates with Scanner, Policy, Feedser, and the attestation chain. It is implementation‑ready. diff --git a/docs/modules/vexer/implementation_plan.md b/docs/modules/vexer/implementation_plan.md new file mode 100644 index 00000000..16318563 --- /dev/null +++ b/docs/modules/vexer/implementation_plan.md @@ -0,0 +1,65 @@ +# Implementation plan — Vexer + +## Delivery phases +- **Phase 1 – Connectors & normalization** + Build connectors for OpenVEX, CSAF VEX, CycloneDX VEX, OCI attestations; capture provenance, signatures, and source metadata; normalise into `VexClaim`. +- **Phase 2 – Mapping & trust registry** + Implement product mapping (CPE → purl/version), issuer registry (trust tiers, signatures), scope scoring, and justification taxonomy. +- **Phase 3 – Consensus & projections** + Deliver consensus computation, conflict preservation, projections (`vex_consensus`, history, provider snapshots), and DSSE events. +- **Phase 4 – APIs & integrations** + Expose REST/CLI endpoints for claims, consensus, conflicts, exports; integrate Policy Engine, Vuln Explorer, Advisory AI, Export Center. +- **Phase 5 – Observability & offline** + Ship metrics, logs, traces, dashboards, incident runbooks, Offline Kit bundles, and performance tuning (10M claims/tenant). + +## Work breakdown +- **Connectors** + - Fetchers for vendor feeds, CSAF repositories, OpenVEX docs, OCI referrers. + - Signature verification (PGP, cosign, PKI) per source; schema validation; rate limiting. + - Source configuration (trust tier, fetch cadence, blackout windows) stored in metadata registry. +- **Normalization** + - Canonical `VexClaim` schema with deterministic IDs, provenance, supersedes chains. + - Product tree parsing, mapping to canonical product keys and environments. + - Justification and scope scoring derived from source semantics. +- **Consensus & projections** + - Lattice join with precedence rules, conflict tracking, confidence scores, recency decay. + - Append-only history, conflict queue, DSSE events (`vex.consensus.updated`). + - Export-ready JSONL & DSSE bundles for Offline Kit and Export Center. +- **APIs & UX** + - REST endpoints (`/claims`, `/consensus`, `/conflicts`, `/providers`) with tenant RBAC. + - CLI commands `stella vex claims|consensus|conflicts|export`. + - Console modules (list/detail, conflict diagnostics, provider health, simulation hooks). +- **Integrations** + - Policy Engine trust knobs, Vuln Explorer consensus badges, Advisory AI narrative generation, Notify alerts for conflicts. + - Orchestrator jobs for recompute/backfill triggered by Excitator deltas. +- **Observability & Ops** + - Metrics (ingest latency, signature failure rate, conflict rate, consensus latency). + - Logs/traces with tenant/issuer/provenance context. + - Runbooks for mapping failures, signature errors, recompute storms, quota exhaustion. + +## Acceptance criteria +- Connectors ingest validated VEX statements with signed provenance, deterministic mapping, and tenant isolation. +- Consensus outputs reproducible, include conflicts, and integrate with Policy Engine/Vuln Explorer/Export Center. +- CLI/Console provide evidence inspection, conflict analysis, and exports; Offline Kit bundles replay verification offline. +- Observability dashboards/alerts capture ingest health, trust anomalies, conflict spikes, and performance budgets. +- Recompute pipeline handles policy changes and new evidence without dropping deterministic outcomes. + +## Risks & mitigations +- **Mapping ambiguity:** maintain scope scores, manual overrides, highlight warnings. +- **Signature trust gaps:** issuer registry with auditing, fallback trust policies, tenant overrides. +- **Evidence surges:** orchestrator backpressure, prioritised queues, shardable workers. +- **Performance regressions:** indexing, caching, load tests, budget enforcement. +- **Tenant leakage:** strict RBAC/filters, fuzz tests, compliance reviews. + +## Test strategy +- **Unit:** connector parsers, normalization, mapping conversions, lattice operations. +- **Property:** randomised evidence ensuring commutative consensus and deterministic digests. +- **Integration:** end-to-end pipeline from Excitator to consensus export, policy simulation, conflict handling. +- **Performance:** large feed ingestion, recompute stress, CLI export throughput. +- **Security:** signature tampering, issuer revocation, RBAC. +- **Offline:** export/import verification, DSSE bundle validation. + +## Definition of done +- Connectors, normalization, consensus, APIs, and integrations deployed with telemetry, runbooks, and Offline Kit parity. +- Documentation (overview, architecture, algorithm, issuer registry, API/CLI, runbooks) updated with imposed rule compliance. +- ./TASKS.md and ../../TASKS.md reflect active status and dependencies. diff --git a/docs/VEXER_SCORRING.md b/docs/modules/vexer/scoring.md similarity index 100% rename from docs/VEXER_SCORRING.md rename to docs/modules/vexer/scoring.md diff --git a/docs/modules/vuln-explorer/AGENTS.md b/docs/modules/vuln-explorer/AGENTS.md new file mode 100644 index 00000000..1f9c43c2 --- /dev/null +++ b/docs/modules/vuln-explorer/AGENTS.md @@ -0,0 +1,22 @@ +# Vulnerability Explorer agent guide + +## Mission +Vulnerability Explorer delivers policy-aware triage, investigation, and reporting surfaces for effective findings. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Review ./architecture.md for ledger schema, workflow states, and export requirements. +2. Open ../../implplan/SPRINTS.md and locate stories for this component. +3. Check ./TASKS.md and update status before/after work. +4. Read README/architecture for design context and update as the implementation evolves. + +## Guardrails +- Uphold Aggregation-Only Contract boundaries when consuming ingestion data. +- Preserve determinism and provenance in all derived outputs. +- Document offline/air-gap pathways for any new feature. +- Update telemetry/observability assets alongside feature work. diff --git a/docs/modules/vuln-explorer/README.md b/docs/modules/vuln-explorer/README.md new file mode 100644 index 00000000..1dcc1253 --- /dev/null +++ b/docs/modules/vuln-explorer/README.md @@ -0,0 +1,29 @@ +# StellaOps Vulnerability Explorer + +Vulnerability Explorer delivers policy-aware triage, investigation, and reporting surfaces for effective findings. + +## Responsibilities +- Present policy-evaluated findings with advisory, VEX, SBOM, and runtime context. +- Capture triage workflow in an immutable findings ledger with role-based access. +- Provide pivots, exports, and reports for auditors and operations teams. +- Integrate explain traces, remediation notes, and offline bundles. + +## Key components +- Findings Ledger service + API. +- Console module and CLI verbs for triage workflows. +- Export integrations for reports and evidence packages. + +## Integrations & dependencies +- Policy Engine for effective findings streams. +- Concelier/Excititor for evidence provenance. +- Scheduler for remediation/verification jobs. +- Notify for triage notifications. + +## Operational notes +- Audit logging per Epic 6 requirements. +- Offline-ready CSV/PDF exports with deterministic hashes. +- Dashboards for MTTR and triage throughput. + +## Epic alignment +- Epic 6: Vulnerability Explorer. +- VULN stories tracked in ../../TASKS.md and src/VulnExplorer/**/TASKS.md. diff --git a/docs/modules/vuln-explorer/TASKS.md b/docs/modules/vuln-explorer/TASKS.md new file mode 100644 index 00000000..70868fc8 --- /dev/null +++ b/docs/modules/vuln-explorer/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Vulnerability Explorer + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| VULNERABILITY-EXPLORER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Ensure ./README.md reflects the latest epic deliverables. | Align with ./AGENTS.md | +| VULNERABILITY-EXPLORER-ENG-0001 | TODO | Module Team | Break down epic milestones into actionable stories. | Sync into ../../TASKS.md | +| VULNERABILITY-EXPLORER-OPS-0001 | TODO | Ops Guild | Prepare runbooks/observability assets once MVP lands. | Document outputs in ./README.md | diff --git a/docs/modules/vuln-explorer/architecture.md b/docs/modules/vuln-explorer/architecture.md new file mode 100644 index 00000000..23bf36a2 --- /dev/null +++ b/docs/modules/vuln-explorer/architecture.md @@ -0,0 +1,66 @@ +# Vulnerability Explorer architecture + +> Based on Epic 6 – Vulnerability Explorer; this specification summarises the ledger model, triage workflows, APIs, and export requirements. + +## 1) Ledger data model + +- **Collections / tables** + - `finding_records` – canonical, policy-derived findings enriched with advisory, VEX, SBOM, runtime context. Includes `policyVersion`, `advisoryRawIds`, `vexRawIds`, `sbomComponentId`, and `explainBundleRef`. + - `finding_history` – append-only state transitions (`new`, `triaged`, `accepted_risk`, `remediated`, `false_positive`, etc.) with timestamps, actor, and justification. + - `triage_actions` – discrete operator actions (comment, assignment, remediation note, ticket link) with immutable provenance. + - `remediation_plans` – structured remediation steps (affected assets, deadlines, recommended fixes, auto-generated from SRM/AI hints). + - `reports` – saved report definitions, export manifests, and signatures. + +- **Immutability & provenance** – All updates are append-only; previous state is recoverable. Records capture `tenant`, `artifactId`, `findingKey`, `policyVersion`, `sourceRunId`, `sr mDigest`. + +## 2) Triage workflow + +1. **Ingest effective findings** from Policy Engine (stream `policy.finding.delta`). Each delta updates `finding_records`, generates history entries, and triggers notification rules. +2. **Prioritisation** uses contextual heuristics: runtime exposure, VEX status, policy severity, AI hints. Stored as `priorityScore` with provenance from Zastava/AI modules. +3. **Assignment & collaboration** – Operators claim findings, add comments, attach evidence, and link tickets. Assignment uses Authority identities and RBAC. +4. **Remediation tracking** – Link remediation plans, record progress, and integrate with Scheduler for follow-up scans once fixes deploy. +5. **Closure** – When Policy or rescans mark finding resolved, system logs closure with explain trace and updates audit ledger. + +State machine summary: + +``` +new -> (triage) triaged -> (remediate) in_progress -> (verify) awaiting_verification -> (scan) remediated +new -> (false_positive) closed_false_positive +new -> (risk_accept) accepted_risk +``` + +All transitions require justification; certain transitions (accepted risk) require multi-approver workflow defined by Policy Studio. + +## 3) APIs + +- `GET /v1/findings` — filtered listing with pagination, search (artifact, advisory, priority, status, assignee). +- `GET /v1/findings/{id}` — detail view (policy context, explain trace, evidence timeline). +- `POST /v1/findings/{id}/actions` — create triage action (assign, comment, status change, remediation, ticket link) with DSSE signature support. +- `POST /v1/reports` — generate report artifact (JSON, CSV, PDF) defined by saved templates; records manifest + signature. +- `GET /v1/exports/offline` — stream deterministic bundle for Offline Kit (findings JSON, history, attachments, manifest). + +CLI mirrors these endpoints (`stella findings list|view|update|export`). Console UI consumes the same APIs via typed clients. + +## 4) AI/automation integration + +- Advisory AI contributes remediation hints and conflict explanations stored alongside findings (`aiInsights`). +- Scheduler integration triggers follow-up scans or policy re-evaluation when remediation plan reaches checkpoint. +- Zastava (Differential SBOM) feeds runtime exposure signals to reprioritise findings automatically. + +## 5) Observability & compliance + +- Metrics: `findings_open_total{severity,tenant}`, `findings_mttr_seconds`, `triage_actions_total{type}`, `report_generation_seconds`. +- Logs: structured with `findingId`, `artifactId`, `advisory`, `policyVersion`, `actor`, `actionType`. +- Audit exports: `audit_log.jsonl` appended whenever state changes; offline bundles include signed audit log and manifest. +- Compliance: accepted risk requires dual approval and stores justification plus expiry reminders (raised through Notify). + +## 6) Offline bundle requirements + +- Bundle structure: + - `manifest.json` (hashes, counts, policy version, generation timestamp). + - `findings.jsonl` (current open findings). + - `history.jsonl` (state changes). + - `actions.jsonl` (comments, assignments, tickets). + - `reports/` (generated PDFs/CSVs). + - `signatures/` (DSSE envelopes). +- Bundles produced deterministically; Export Center consumes them for mirror profiles. diff --git a/docs/modules/vuln-explorer/implementation_plan.md b/docs/modules/vuln-explorer/implementation_plan.md new file mode 100644 index 00000000..ca47a9f1 --- /dev/null +++ b/docs/modules/vuln-explorer/implementation_plan.md @@ -0,0 +1,70 @@ +# Implementation plan — Vulnerability Explorer + +## Delivery phases +- **Phase 1 – Findings Ledger & resolver** + Create append-only ledger, projector, ecosystem resolvers (npm/Maven/PyPI/Go/RPM/DEB), canonical advisory keys, and provenance hashing. +- **Phase 2 – API & simulation** + Ship Vuln Explorer API (list/detail/grouping/simulation), batch evaluation with Policy Engine rationales, and export orchestrator. +- **Phase 3 – Console & CLI workflows** + Deliver triage UI (assignments, comments, remediation plans, simulation bar), keyboard accessibility, and CLI commands (`stella vuln ...`) with JSON/CSV output. +- **Phase 4 – Automation & integrations** + Integrate Advisory AI hints, Zastava runtime exposure, Notify rules, Scheduler follow-up scans, and Graph Explorer deep links. +- **Phase 5 – Exports & offline parity** + Generate deterministic bundles (JSON, CSV, PDF, Offline Kit manifests), audit logs, and signed reports. +- **Phase 6 – Observability & hardening** + Complete dashboards (projection lag, MTTR, accepted-risk cadence), alerts, runbooks, performance tuning (5M findings/tenant), and security/RBAC validation. + +## Work breakdown +- **Findings Ledger** + - Define event schema, Merkle root anchoring, append-only storage, history tables. + - Projector to `finding_records` and `finding_history`, idempotent event processing, time travel snapshots. + - Resolver pipelines referencing SBOM inventory deltas, policy outputs, VEX consensus, runtime signals. +- **API & exports** + - REST endpoints (`/v1/findings`, `/v1/findings/{id}`, `/actions`, `/reports`, `/exports`) with ABAC filters. + - Simulation endpoint returning diffs, integration with Policy Engine batch evaluation. + - Export jobs for JSON/CSV/PDF plus Offline Kit bundle assembly and signing. +- **Console** + - Feature module `vuln-explorer` with grid, filters, saved views, deep links, detail tabs (policy, evidence, paths, remediation). + - Simulation drawer, delta chips, accepted-risk approvals, evidence bundle viewer. + - Accessibility (keyboard navigation, ARIA), virtualization for large result sets. +- **CLI** + - Commands `stella vuln list|show|simulate|assign|accept-risk|verify-fix|export`. + - Stable schemas for automation; piping support; tests for exit codes. +- **Integrations** + - Conseiller/Excitator: normalized advisory keys, linksets, evidence retrieval. + - SBOM Service: inventory deltas with scope/runtime flags, safe version hints. + - Notify: events for SLA breaches, accepted-risk expiries, remediation deadlines. + - Scheduler: trigger rescans when remediation plan milestones complete. +- **Observability & ops** + - Metrics (open findings, MTTR, projection lag, export duration, SLA burn), logs/traces with correlation IDs. + - Alerting on projector backlog, API 5xx spikes, export failures, accepted-risk nearing expiry. + - Runbooks covering recompute storms, mapping errors, report issues. + +## Acceptance criteria +- Ledger/event sourcing reproduces historical states byte-for-byte; Merkle hashes verify integrity. +- Resolver respects ecosystem semantics, scope, and runtime context; path evidence presented in UI/CLI. +- Triage workflows (assignment, comments, accepted-risk) enforce justification and approval requirements with audit records. +- Simulation returns policy diffs without mutating state; CLI/UI parity achieved for simulation and exports. +- Exports and Offline Kit bundles reproducible with signed manifests and provenance; reports available in JSON/CSV/PDF. +- Observability dashboards show green SLOs, alerts fire for projection lag or SLA burns, and runbooks documented. +- RBAC/ABAC validated; attachments encrypted; tenant isolation guaranteed. + +## Risks & mitigations +- **Advisory identity collisions:** strict canonicalization, linkset references, raw evidence access. +- **Resolver inaccuracies:** property-based tests, path verification, manual override workflows. +- **Projection lag/backlog:** autoscaling, queue backpressure, alerting, pause controls. +- **Export size/performance:** streaming NDJSON, size estimators, chunked downloads. +- **User confusion on suppression:** rationale tab, explicit badges, explain traces. + +## Test strategy +- **Unit:** resolver algorithms, state machine transitions, policy mapping, export builders. +- **Integration:** ingestion → ledger → projector → API flow, simulation, Notify notifications. +- **E2E:** Console triage scenarios, CLI flows, accessibility tests. +- **Performance:** 5M findings/tenant, projection rebuild, export generation. +- **Security:** RBAC/ABAC matrix, CSRF, attachment encryption, signed URL expiry. +- **Determinism:** time-travel snapshots, export manifest hashing, Offline Kit replay. + +## Definition of done +- Services, UI/CLI, integrations, exports, and observability deployed with runbooks and Offline Kit parity. +- Documentation suite (overview, using-console, API, CLI, findings ledger, policy mapping, VEX/SBOM integration, telemetry, security, runbooks, install) updated with imposed rule statement. +- ./TASKS.md and ../../TASKS.md reflect active progress; compliance checklists appended where required. diff --git a/docs/modules/zastava/AGENTS.md b/docs/modules/zastava/AGENTS.md new file mode 100644 index 00000000..488db0c8 --- /dev/null +++ b/docs/modules/zastava/AGENTS.md @@ -0,0 +1,22 @@ +# Zastava agent guide + +## Mission +Zastava monitors running workloads, verifies supply chain posture, and enforces runtime policy via Kubernetes admission webhooks. + +## Key docs +- [Module README](./README.md) +- [Architecture](./architecture.md) +- [Implementation plan](./implementation_plan.md) +- [Task board](./TASKS.md) + +## How to get started +1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module. +2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED). +3. Read the architecture and README for domain context before editing code or docs. +4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan. + +## Guardrails +- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md). +- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts. +- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature. +- Update runbooks/observability assets when operational characteristics change. \ No newline at end of file diff --git a/docs/modules/zastava/README.md b/docs/modules/zastava/README.md new file mode 100644 index 00000000..622ceb3f --- /dev/null +++ b/docs/modules/zastava/README.md @@ -0,0 +1,33 @@ +# StellaOps Zastava + +Zastava monitors running workloads, verifies supply chain posture, and enforces runtime policy via Kubernetes admission webhooks. + +## Responsibilities +- Observe node/container activity and emit runtime events. +- Validate signatures, SBOM presence, and backend verdicts before allowing containers. +- Buffer and replay events during disconnections. +- Trigger delta scans when runtime posture drifts. + +## Key components +- `StellaOps.Zastava.Observer` daemonset. +- `StellaOps.Zastava.Webhook` admission controller. +- Shared contracts in `StellaOps.Zastava.Core`. + +## Integrations & dependencies +- Authority for OpToks and mTLS. +- Scanner/Scheduler for remediation triggers. +- Notify/UI for runtime alerts and dashboards. + +## Operational notes +- Runbook ./operations/runtime.md with Grafana/Prometheus assets. +- Offline kit assets bundling webhook charts. +- DPoP/mTLS rotation guidance shared with Authority. + +## Related resources +- ./operations/runtime.md +- ./operations/runtime-grafana-dashboard.json +- ./operations/runtime-prometheus-rules.yaml + +## Backlog references +- ZASTAVA runtime tasks in ../../TASKS.md. +- Webhook smoke tests tracked in src/Zastava/**/TASKS.md. diff --git a/docs/modules/zastava/TASKS.md b/docs/modules/zastava/TASKS.md new file mode 100644 index 00000000..c0c3b4eb --- /dev/null +++ b/docs/modules/zastava/TASKS.md @@ -0,0 +1,9 @@ +# Task board — Zastava + +> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable. + +| ID | Status | Owner(s) | Description | Notes | +|----|--------|----------|-------------|-------| +| ZASTAVA-DOCS-0001 | TODO | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md | +| ZASTAVA-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md | +| ZASTAVA-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow | diff --git a/docs/ARCHITECTURE_ZASTAVA.md b/docs/modules/zastava/architecture.md similarity index 100% rename from docs/ARCHITECTURE_ZASTAVA.md rename to docs/modules/zastava/architecture.md diff --git a/docs/modules/zastava/implementation_plan.md b/docs/modules/zastava/implementation_plan.md new file mode 100644 index 00000000..c8626951 --- /dev/null +++ b/docs/modules/zastava/implementation_plan.md @@ -0,0 +1,19 @@ +# Implementation plan — Zastava + +## Current objectives +- Maintain deterministic behaviour and offline parity across releases. +- Keep documentation, telemetry, and runbooks aligned with the latest sprint outcomes. + +## Workstreams +- Backlog grooming: reconcile open stories in ../../TASKS.md with this module's roadmap. +- Implementation: collaborate with service owners to land feature work defined in SPRINTS/EPIC docs. +- Validation: extend tests/fixtures to preserve determinism and provenance requirements. + +## Backlog references +- ZASTAVA runtime tasks in ../../TASKS.md. +- Webhook smoke tests tracked in src/Zastava/**/TASKS.md. + +## Coordination +- Review ./AGENTS.md before picking up new work. +- Sync with cross-cutting teams noted in ../../implplan/SPRINTS.md. +- Update this plan whenever scope, dependencies, or guardrails change. diff --git a/docs/ops/zastava-runtime-grafana-dashboard.json b/docs/modules/zastava/operations/runtime-grafana-dashboard.json similarity index 100% rename from docs/ops/zastava-runtime-grafana-dashboard.json rename to docs/modules/zastava/operations/runtime-grafana-dashboard.json diff --git a/docs/ops/zastava-runtime-prometheus-rules.yaml b/docs/modules/zastava/operations/runtime-prometheus-rules.yaml similarity index 100% rename from docs/ops/zastava-runtime-prometheus-rules.yaml rename to docs/modules/zastava/operations/runtime-prometheus-rules.yaml diff --git a/docs/ops/zastava-runtime-operations.md b/docs/modules/zastava/operations/runtime.md similarity index 94% rename from docs/ops/zastava-runtime-operations.md rename to docs/modules/zastava/operations/runtime.md index 700dfb9a..d6884b46 100644 --- a/docs/ops/zastava-runtime-operations.md +++ b/docs/modules/zastava/operations/runtime.md @@ -116,7 +116,7 @@ It aligns with `Sprint 12 – Runtime Guardrails` and assumes components consume - Bundle contents: - Observer/Webhook container images (multi-arch). - - `docs/ops/zastava-runtime-prometheus-rules.yaml` + Grafana dashboard JSON. +- `docs/modules/zastava/operations/runtime-prometheus-rules.yaml` + Grafana dashboard JSON. - Sample `zastava-runtime.values.yaml`. - Verification: - Validate signature: `cosign verify-blob offline-kit/zastava-runtime-*.tar.zst --certificate offline-kit/zastava-runtime.cert`. @@ -125,8 +125,8 @@ It aligns with `Sprint 12 – Runtime Guardrails` and assumes components consume ## 6. Observability assets -- Prometheus alert rules: `docs/ops/zastava-runtime-prometheus-rules.yaml`. -- Grafana dashboard JSON: `docs/ops/zastava-runtime-grafana-dashboard.json`. +- Prometheus alert rules: `docs/modules/zastava/operations/runtime-prometheus-rules.yaml`. +- Grafana dashboard JSON: `docs/modules/zastava/operations/runtime-grafana-dashboard.json`. - Add both to the monitoring repo (`ops/monitoring/zastava`) and reference them in the Offline Kit manifest. diff --git a/docs/notifications/digests.md b/docs/notifications/digests.md index 0e7780d2..16ba200e 100644 --- a/docs/notifications/digests.md +++ b/docs/notifications/digests.md @@ -1,92 +1,92 @@ -# Notifications Digests - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -Digests coalesce multiple matching events into a single notification when rules request batched delivery. They protect responders from alert storms while preserving a deterministic record of every input. - ---- - -## 1. Digest lifecycle - -1. **Window selection.** Rule actions opt into a digest cadence by setting `actions[].digest` (`instant`, `5m`, `15m`, `1h`, `1d`). `instant` skips digest logic entirely. -2. **Aggregation.** When an event matches, the worker appends it to the open digest window (`tenantId + actionId + window`). Events include the canonical scope, delta counts, and references. -3. **Flush.** When the window expires or hits the worker’s safety cap (configurable), the worker renders a digest template and emits a single delivery with status `Digested`. -4. **Audit.** The delivery ledger links back to the digest document so operators can inspect individual items and the aggregated summary. - ---- - -## 2. Storage model - -Digest state lives in Mongo (`digests` collection) and mirrors the schema described in [ARCHITECTURE_NOTIFY.md](../ARCHITECTURE_NOTIFY.md#7-data-model-mongo): - -```json -{ - "_id": "tenant-dev:act-email-compliance:1h", - "tenantId": "tenant-dev", - "actionKey": "act-email-compliance", - "window": "1h", - "openedAt": "2025-10-24T08:00:00Z", - "status": "open", - "items": [ - { - "eventId": "00000000-0000-0000-0000-000000000001", - "scope": { - "namespace": "prod-payments", - "repo": "ghcr.io/acme/api", - "digest": "sha256:…" - }, - "delta": { - "newCritical": 1, - "kev": 1 - } - } - ] -} -``` - -- `status` reflects whether the window is currently collecting (`open`) or has been completed (`closed`). Future revisions may introduce `flushing` for in-progress operations. -- `items[].delta` captures aggregated counts for reporting (e.g., new critical findings, KEV, quieted). -- Workers use optimistic concurrency on the document ID to avoid duplicate flushes across replicas. - ---- - -## 3. Rendering and templates - -- Digest deliveries use the same template engine as instant notifications. Templates receive an additional `digest` object with `window`, `openedAt`, `itemCount`, and `items` (findings grouped by namespace/repository when available). -- Provide digest-specific templates (e.g., `tmpl-digest-hourly`) so the body can enumerate top offenders, summarise totals, and link to detailed dashboards. -- When no template is specified, Notify falls back to channel defaults that emphasise summary counts and redirect to Console for detail. - ---- - -## 4. API surface - -| Endpoint | Description | Notes | -|----------|-------------|-------| -| `POST /digests` | Issues administrative commands (e.g., force flush, reopen) for a specific action/window. | Request body specifies the command target; requires `notify.admin`. | -| `GET /digests/{actionKey}` | Returns the currently open window (if any) for the referenced action. | Supports operators/CLI inspecting pending digests; requires `notify.read`. | -| `DELETE /digests/{actionKey}` | Drops the open window without notifying (emergency stop). | Emits an audit record; use sparingly. | - -All routes honour the tenant header and reuse the standard Notify rate limits. - ---- - -## 5. Worker behaviour and safety nets - -- **Idempotency.** Flush operations generate a deterministic digest delivery ID (`digest::::`). Retries reuse the same ID. -- **Throttles.** Digest generation respects action throttles; setting an aggressive throttle together with a digest window may result in deliberate skips (logged as `Throttled` in the delivery ledger). -- **Quiet hours.** Future sprint work (`NOTIFY-SVC-39-004`) integrates quiet-hour calendars. When enabled, flush timers pause during quiet windows and resume afterwards. -- **Back-pressure.** When the window reaches the configured item cap before the timer, the worker flushes early and starts a new window immediately. -- **Crash resilience.** Workers rebuild in-flight windows from Mongo on startup; partially flushed windows remain closed after success or reopened if the flush fails. - ---- - -## 6. Operator guidance - -- Choose hourly digests for high-volume compliance events; daily digests suit executive reporting. -- Pair digests with incident-focused instant rules so critical items surface immediately while less urgent noise is summarised. -- Monitor `/stats` output for `openDigestCount` to ensure windows are flushing; spikes may indicate downstream connector failures. -- When testing new digest templates, open a small (`5m`) window, trigger sample events, then call `POST /digests/{actionId}/flush` to validate rendering before moving to longer cadences. - ---- - -> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Notifications Digests + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +Digests coalesce multiple matching events into a single notification when rules request batched delivery. They protect responders from alert storms while preserving a deterministic record of every input. + +--- + +## 1. Digest lifecycle + +1. **Window selection.** Rule actions opt into a digest cadence by setting `actions[].digest` (`instant`, `5m`, `15m`, `1h`, `1d`). `instant` skips digest logic entirely. +2. **Aggregation.** When an event matches, the worker appends it to the open digest window (`tenantId + actionId + window`). Events include the canonical scope, delta counts, and references. +3. **Flush.** When the window expires or hits the worker’s safety cap (configurable), the worker renders a digest template and emits a single delivery with status `Digested`. +4. **Audit.** The delivery ledger links back to the digest document so operators can inspect individual items and the aggregated summary. + +--- + +## 2. Storage model + +Digest state lives in Mongo (`digests` collection) and mirrors the schema described in [modules/notify/architecture.md](../modules/notify/architecture.md#7-data-model-mongo): + +```json +{ + "_id": "tenant-dev:act-email-compliance:1h", + "tenantId": "tenant-dev", + "actionKey": "act-email-compliance", + "window": "1h", + "openedAt": "2025-10-24T08:00:00Z", + "status": "open", + "items": [ + { + "eventId": "00000000-0000-0000-0000-000000000001", + "scope": { + "namespace": "prod-payments", + "repo": "ghcr.io/acme/api", + "digest": "sha256:…" + }, + "delta": { + "newCritical": 1, + "kev": 1 + } + } + ] +} +``` + +- `status` reflects whether the window is currently collecting (`open`) or has been completed (`closed`). Future revisions may introduce `flushing` for in-progress operations. +- `items[].delta` captures aggregated counts for reporting (e.g., new critical findings, KEV, quieted). +- Workers use optimistic concurrency on the document ID to avoid duplicate flushes across replicas. + +--- + +## 3. Rendering and templates + +- Digest deliveries use the same template engine as instant notifications. Templates receive an additional `digest` object with `window`, `openedAt`, `itemCount`, and `items` (findings grouped by namespace/repository when available). +- Provide digest-specific templates (e.g., `tmpl-digest-hourly`) so the body can enumerate top offenders, summarise totals, and link to detailed dashboards. +- When no template is specified, Notify falls back to channel defaults that emphasise summary counts and redirect to Console for detail. + +--- + +## 4. API surface + +| Endpoint | Description | Notes | +|----------|-------------|-------| +| `POST /digests` | Issues administrative commands (e.g., force flush, reopen) for a specific action/window. | Request body specifies the command target; requires `notify.admin`. | +| `GET /digests/{actionKey}` | Returns the currently open window (if any) for the referenced action. | Supports operators/CLI inspecting pending digests; requires `notify.read`. | +| `DELETE /digests/{actionKey}` | Drops the open window without notifying (emergency stop). | Emits an audit record; use sparingly. | + +All routes honour the tenant header and reuse the standard Notify rate limits. + +--- + +## 5. Worker behaviour and safety nets + +- **Idempotency.** Flush operations generate a deterministic digest delivery ID (`digest::::`). Retries reuse the same ID. +- **Throttles.** Digest generation respects action throttles; setting an aggressive throttle together with a digest window may result in deliberate skips (logged as `Throttled` in the delivery ledger). +- **Quiet hours.** Future sprint work (`NOTIFY-SVC-39-004`) integrates quiet-hour calendars. When enabled, flush timers pause during quiet windows and resume afterwards. +- **Back-pressure.** When the window reaches the configured item cap before the timer, the worker flushes early and starts a new window immediately. +- **Crash resilience.** Workers rebuild in-flight windows from Mongo on startup; partially flushed windows remain closed after success or reopened if the flush fails. + +--- + +## 6. Operator guidance + +- Choose hourly digests for high-volume compliance events; daily digests suit executive reporting. +- Pair digests with incident-focused instant rules so critical items surface immediately while less urgent noise is summarised. +- Monitor `/stats` output for `openDigestCount` to ensure windows are flushing; spikes may indicate downstream connector failures. +- When testing new digest templates, open a small (`5m`) window, trigger sample events, then call `POST /digests/{actionId}/flush` to validate rendering before moving to longer cadences. + +--- + +> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/notifications/overview.md b/docs/notifications/overview.md index 82a434fb..94a946a4 100644 --- a/docs/notifications/overview.md +++ b/docs/notifications/overview.md @@ -1,76 +1,76 @@ -# Notifications Overview - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -Notifications Studio turns raw platform events into concise, tenant-scoped alerts that reach the right responders without overwhelming them. The service is sovereign/offline-first, follows the Aggregation-Only Contract (AOC), and produces deterministic outputs so the same configuration yields identical deliveries across environments. - ---- - -## 1. Mission & value - -- **Reduce noise.** Only materially new or high-impact changes reach chat, email, or webhooks thanks to rule filters, throttles, and digest windows. -- **Explainable results.** Every delivery is traceable back to a rule, action, and event payload stored in the delivery ledger; operators can audit what fired and why. -- **Safe by default.** Secrets remain in external stores, templates are sandboxed, quiet hours and throttles prevent storms, and idempotency guarantees protect downstream systems. -- **Offline-aligned.** All configuration, templates, and plug-ins ship with Offline Kits; no external SaaS is required to send notifications. - ---- - -## 2. Core capabilities - -| Capability | What it does | Key docs | -|------------|--------------|----------| -| Rules engine | Declarative matchers for event kinds, severities, namespaces, VEX context, KEV flags, and more. | [`notifications/rules.md`](rules.md) | -| Channel catalog | Slack, Teams, Email, Webhook connectors loaded via restart-time plug-ins; metadata stored without secrets. | [`notifications/architecture.md`](architecture.md) | -| Templates | Locale-aware, deterministic rendering via safe helpers; channel defaults plus tenant-specific overrides. | [`notifications/templates.md`](templates.md) | -| Digests | Coalesce bursts into periodic summaries with deterministic IDs and audit trails. | [`notifications/digests.md`](digests.md) | -| Delivery ledger | Tracks rendered payload hashes, attempts, throttles, and outcomes for every action. | [`ARCHITECTURE_NOTIFY.md`](../ARCHITECTURE_NOTIFY.md#7-data-model-mongo) | - ---- - -## 3. How it fits into Stella Ops - -1. **Producers emit events.** Scanner, Scheduler, VEX Lens, Attestor, and Zastava publish canonical envelopes (`NotifyEvent`) onto the internal bus. -2. **Notify.Worker evaluates rules.** For each tenant, the worker applies match filters, VEX gates, throttles, and digest policies before rendering the action. -3. **Connectors deliver.** Channel plug-ins send the rendered payload to Slack/Teams/Email/Webhook targets and report back attempts and outcomes. -4. **Consumers investigate.** Operators pivot from message links into Console dashboards, SBOM views, or policy overlays with correlation IDs preserved. - -The Notify WebService fronts worker state with REST APIs used by the UI and CLI. Tenants authenticate via StellaOps Authority scopes `notify.read` and `notify.admin`. All operations require the tenant header (`X-StellaOps-Tenant`) to preserve sovereignty boundaries. - ---- - -## 4. Operating model - -| Area | Guidance | -|------|----------| -| **Tenancy** | Each rule, channel, template, and delivery belongs to exactly one tenant. Cross-tenant sharing is intentionally unsupported. | -| **Determinism** | Configuration persistence normalises strings and sorts collections. Template rendering produces identical `bodyHash` values when inputs match. | -| **Scaling** | Workers scale horizontally; per-tenant rule snapshots are cached and refreshed from Mongo change streams. Redis (or equivalent) guards throttles and locks. | -| **Offline** | Offline Kits include plug-ins, default templates, and seed rules. Operators can edit YAML/JSON manifests before air-gapped deployment. | -| **Security** | Channel secrets use indirection (`secretRef`), Authority-protected OAuth clients secure API access, and delivery payloads are redacted before storage where required. | - ---- - -## 5. Getting started (first 30 minutes) - -| Step | Goal | Reference | -|------|------|-----------| -| 1 | Deploy Notify WebService + Worker with Mongo and Redis | [`ARCHITECTURE_NOTIFY.md`](../ARCHITECTURE_NOTIFY.md#1-runtime-shape--projects) | -| 2 | Register OAuth clients/scopes in Authority | [`etc/authority.yaml.sample`](../etc/authority.yaml.sample) | -| 3 | Install channel plug-ins and capture secret references | [`plugins/notify`](../../plugins) | -| 4 | Create a tenant rule and test preview | [`POST /channels/{id}/test`](../ARCHITECTURE_NOTIFY.md#8-external-apis-webservice) | -| 5 | Inspect deliveries and digests | `/api/v1/notify/deliveries`, `/api/v1/notify/digests` | - ---- - -## 6. Alignment with implementation work - -| Backlog item | Impact on docs | Status | -|--------------|----------------|--------| -| `NOTIFY-SVC-38-001..004` | Foundational correlation, throttling, simulation hooks. | **In progress** – align behaviour once services publish beta APIs. | -| `NOTIFY-SVC-39-001..004` | Adds correlation engine, digest generator, simulation API, quiet hours. | **Pending** – revisit rule/digest sections when these tasks merge. | - -Action: coordinate with the Notifications Service Guild when `NOTIFY-SVC-39-001..004` land to validate payload fields, quiet-hours semantics, and any new connector metadata that should be documented here and in the channel-specific guides. - ---- - -> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Notifications Overview + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +Notifications Studio turns raw platform events into concise, tenant-scoped alerts that reach the right responders without overwhelming them. The service is sovereign/offline-first, follows the Aggregation-Only Contract (AOC), and produces deterministic outputs so the same configuration yields identical deliveries across environments. + +--- + +## 1. Mission & value + +- **Reduce noise.** Only materially new or high-impact changes reach chat, email, or webhooks thanks to rule filters, throttles, and digest windows. +- **Explainable results.** Every delivery is traceable back to a rule, action, and event payload stored in the delivery ledger; operators can audit what fired and why. +- **Safe by default.** Secrets remain in external stores, templates are sandboxed, quiet hours and throttles prevent storms, and idempotency guarantees protect downstream systems. +- **Offline-aligned.** All configuration, templates, and plug-ins ship with Offline Kits; no external SaaS is required to send notifications. + +--- + +## 2. Core capabilities + +| Capability | What it does | Key docs | +|------------|--------------|----------| +| Rules engine | Declarative matchers for event kinds, severities, namespaces, VEX context, KEV flags, and more. | [`notifications/rules.md`](rules.md) | +| Channel catalog | Slack, Teams, Email, Webhook connectors loaded via restart-time plug-ins; metadata stored without secrets. | [`notifications/architecture.md`](architecture.md) | +| Templates | Locale-aware, deterministic rendering via safe helpers; channel defaults plus tenant-specific overrides. | [`notifications/templates.md`](templates.md) | +| Digests | Coalesce bursts into periodic summaries with deterministic IDs and audit trails. | [`notifications/digests.md`](digests.md) | +| Delivery ledger | Tracks rendered payload hashes, attempts, throttles, and outcomes for every action. | [`modules/notify/architecture.md`](../modules/notify/architecture.md#7-data-model-mongo) | + +--- + +## 3. How it fits into Stella Ops + +1. **Producers emit events.** Scanner, Scheduler, VEX Lens, Attestor, and Zastava publish canonical envelopes (`NotifyEvent`) onto the internal bus. +2. **Notify.Worker evaluates rules.** For each tenant, the worker applies match filters, VEX gates, throttles, and digest policies before rendering the action. +3. **Connectors deliver.** Channel plug-ins send the rendered payload to Slack/Teams/Email/Webhook targets and report back attempts and outcomes. +4. **Consumers investigate.** Operators pivot from message links into Console dashboards, SBOM views, or policy overlays with correlation IDs preserved. + +The Notify WebService fronts worker state with REST APIs used by the UI and CLI. Tenants authenticate via StellaOps Authority scopes `notify.read` and `notify.admin`. All operations require the tenant header (`X-StellaOps-Tenant`) to preserve sovereignty boundaries. + +--- + +## 4. Operating model + +| Area | Guidance | +|------|----------| +| **Tenancy** | Each rule, channel, template, and delivery belongs to exactly one tenant. Cross-tenant sharing is intentionally unsupported. | +| **Determinism** | Configuration persistence normalises strings and sorts collections. Template rendering produces identical `bodyHash` values when inputs match. | +| **Scaling** | Workers scale horizontally; per-tenant rule snapshots are cached and refreshed from Mongo change streams. Redis (or equivalent) guards throttles and locks. | +| **Offline** | Offline Kits include plug-ins, default templates, and seed rules. Operators can edit YAML/JSON manifests before air-gapped deployment. | +| **Security** | Channel secrets use indirection (`secretRef`), Authority-protected OAuth clients secure API access, and delivery payloads are redacted before storage where required. | + +--- + +## 5. Getting started (first 30 minutes) + +| Step | Goal | Reference | +|------|------|-----------| +| 1 | Deploy Notify WebService + Worker with Mongo and Redis | [`modules/notify/architecture.md`](../modules/notify/architecture.md#1-runtime-shape--projects) | +| 2 | Register OAuth clients/scopes in Authority | [`etc/authority.yaml.sample`](../etc/authority.yaml.sample) | +| 3 | Install channel plug-ins and capture secret references | [`plugins/notify`](../../plugins) | +| 4 | Create a tenant rule and test preview | [`POST /channels/{id}/test`](../modules/notify/architecture.md#8-external-apis-webservice) | +| 5 | Inspect deliveries and digests | `/api/v1/notify/deliveries`, `/api/v1/notify/digests` | + +--- + +## 6. Alignment with implementation work + +| Backlog item | Impact on docs | Status | +|--------------|----------------|--------| +| `NOTIFY-SVC-38-001..004` | Foundational correlation, throttling, simulation hooks. | **In progress** – align behaviour once services publish beta APIs. | +| `NOTIFY-SVC-39-001..004` | Adds correlation engine, digest generator, simulation API, quiet hours. | **Pending** – revisit rule/digest sections when these tasks merge. | + +Action: coordinate with the Notifications Service Guild when `NOTIFY-SVC-39-001..004` land to validate payload fields, quiet-hours semantics, and any new connector metadata that should be documented here and in the channel-specific guides. + +--- + +> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/notifications/templates.md b/docs/notifications/templates.md index fbb53cf8..c28171eb 100644 --- a/docs/notifications/templates.md +++ b/docs/notifications/templates.md @@ -1,130 +1,130 @@ -# Notifications Templates - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - -Templates shape the payload rendered for each channel when a rule action fires. They are deterministic, locale-aware artefacts stored alongside rules so Notify.Worker replicas can render identical messages regardless of environment. - ---- - -## 1. Template lifecycle - -1. **Authoring.** Operators create templates via the API (`POST /templates`) or UI. Each template binds to a channel type (`Slack`, `Teams`, `Email`, `Webhook`, `Custom`) and a locale. -2. **Reference.** Rule actions opt in by referencing the template key (`actions[].template`). Channel defaults apply when no template is specified. -3. **Rendering.** During delivery, the worker resolves the template (locale fallbacks included), executes it using the safe Handlebars-style engine, and passes the rendered payload plus metadata to the connector. -4. **Audit.** Rendered payloads stored in the delivery ledger include the `templateId` so operators can trace which text was used. - ---- - -## 2. Template schema reference - -| Field | Type | Notes | -|-------|------|-------| -| `templateId` | string | Stable identifier (UUID/slug). | -| `tenantId` | string | Must match the tenant header in API calls. | -| `channelType` | [`NotifyChannelType`](../ARCHITECTURE_NOTIFY.md#5-channels--connectors-plug-ins) | Determines connector payload envelope. | -| `key` | string | Human-readable key referenced by rules (`tmpl-critical`). | -| `locale` | string | BCP-47 tag, stored lower-case (`en-us`, `bg-bg`). | -| `body` | string | Template body; rendered strictly without executing arbitrary code. | -| `renderMode` | enum | `Markdown`, `Html`, `AdaptiveCard`, `PlainText`, or `Json`. Guides connector sanitisation. | -| `format` | enum | `Slack`, `Teams`, `Email`, `Webhook`, or `Json`. Signals delivery payload structure. | -| `description` | string? | Optional operator note. | -| `metadata` | map | Sorted map for automation (layout hints, fallback text). | -| `createdBy`/`createdAt` | string?, instant | Auto-populated. | -| `updatedBy`/`updatedAt` | string?, instant | Auto-populated. | -| `schemaVersion` | string | Auto-upgraded on persistence. | - -Templates are normalised: string fields trimmed, locale lower-cased, metadata sorted to preserve determinism. - ---- - -## 3. Variables, helpers, and context - -Templates receive a structured context derived from the Notify event, rule match, and rendering metadata. - -| Path | Description | -|------|-------------| -| `event.*` | Canonical event envelope (`kind`, `tenant`, `ts`, `actor`). | -| `event.scope.*` | Namespace, repository, digest, image, component identifiers, labels, attributes. | -| `payload.*` | Raw event payload (e.g., `payload.verdict`, `payload.delta.*`, `payload.links.*`). | -| `rule.*` | Rule descriptor (`ruleId`, `name`, `labels`, `metadata`). | -| `action.*` | Action descriptor (`actionId`, `channel`, `digest`, `throttle`, `metadata`). | -| `policy.*` | Policy metadata when supplied (`revisionId`, `name`). | -| `topFindings[]` | Top-N findings summarised for convenience (vulnerability ID, severity, reachability). | -| `digest.*` | When rendering digest flushes: `window`, `openedAt`, `itemCount`. | - -Built-in helpers mirror the architecture dossier: - -| Helper | Usage | -|--------|-------| -| `severity_icon severity` | Returns emoji/text badge representing severity. | -| `link text url` | Produces channel-safe hyperlink. | -| `pluralize count "finding"` | Adds plural suffix when `count != 1`. | -| `truncate text maxLength` | Cuts strings while preserving determinism. | -| `code text` | Formats inline code (Markdown/HTML aware). | - -Connectors may expose additional helpers via partials, but must remain deterministic and side-effect free. - ---- - -## 4. Sample templates - -### 4.1 Slack (Markdown + block kit) - -```hbs -{{#*inline "findingLine"}} -- {{severity_icon severity}} {{vulnId}} ({{severity}}) in `{{component}}` -{{/inline}} - -*:rotating_light: {{payload.summary.total}} findings {{#if payload.delta.newCritical}}(new critical: {{payload.delta.newCritical}}){{/if}}* - -{{#if topFindings.length}} -Top findings: -{{#each topFindings}}{{> findingLine}}{{/each}} -{{/if}} - -{{link "Open report in Console" payload.links.ui}} -``` - -### 4.2 Email (HTML + text alternative) - -```hbs -

{{payload.verdict}} for {{event.scope.repo}}

-

{{payload.summary.total}} findings ({{payload.summary.blocked}} blocked, {{payload.summary.warned}} warned)

- - - - {{#each topFindings}} - - - - - - {{/each}} - -
FindingSeverityPackage
{{this.vulnId}}{{this.severity}}{{this.component}}
-

{{link "View full analysis" payload.links.ui}}

-``` - -When delivering via email, connectors automatically attach a plain-text alternative derived from the rendered content to preserve accessibility. - ---- - -## 5. Preview and validation - -- `POST /channels/{id}/test` accepts an optional `templateId` and sample payload to produce a rendered preview without dispatching the event. Results include channel type, target, title/summary, locale, body hash, and connector metadata. -- UI previews rely on the same API and highlight connector fallbacks (e.g., Teams adaptive card vs. text fallback). -- Offline Kit scenarios can call `/internal/notify/templates/normalize` to ensure bundled templates match the canonical schema before packaging. - ---- - -## 6. Best practices - -- Keep channel-specific limits in mind (Slack block/character quotas, Teams adaptive card size, email line length). Lean on digests to summarise long lists. -- Provide locale-specific versions for high-volume tenants; Notify selects the closest locale, falling back to `en-us`. -- Store connector-specific hints (`metadata.layout`, `metadata.emoji`) in template metadata rather than rules when they affect rendering. -- Version template bodies through metadata (e.g., `metadata.revision: "2025-10-28"`) so tenants can track changes over time. -- Run test previews whenever introducing new helpers to confirm body hashes remain stable across environments. - ---- - -> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. +# Notifications Templates + +> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +Templates shape the payload rendered for each channel when a rule action fires. They are deterministic, locale-aware artefacts stored alongside rules so Notify.Worker replicas can render identical messages regardless of environment. + +--- + +## 1. Template lifecycle + +1. **Authoring.** Operators create templates via the API (`POST /templates`) or UI. Each template binds to a channel type (`Slack`, `Teams`, `Email`, `Webhook`, `Custom`) and a locale. +2. **Reference.** Rule actions opt in by referencing the template key (`actions[].template`). Channel defaults apply when no template is specified. +3. **Rendering.** During delivery, the worker resolves the template (locale fallbacks included), executes it using the safe Handlebars-style engine, and passes the rendered payload plus metadata to the connector. +4. **Audit.** Rendered payloads stored in the delivery ledger include the `templateId` so operators can trace which text was used. + +--- + +## 2. Template schema reference + +| Field | Type | Notes | +|-------|------|-------| +| `templateId` | string | Stable identifier (UUID/slug). | +| `tenantId` | string | Must match the tenant header in API calls. | +| `channelType` | [`NotifyChannelType`](../modules/notify/architecture.md#5-channels--connectors-plug-ins) | Determines connector payload envelope. | +| `key` | string | Human-readable key referenced by rules (`tmpl-critical`). | +| `locale` | string | BCP-47 tag, stored lower-case (`en-us`, `bg-bg`). | +| `body` | string | Template body; rendered strictly without executing arbitrary code. | +| `renderMode` | enum | `Markdown`, `Html`, `AdaptiveCard`, `PlainText`, or `Json`. Guides connector sanitisation. | +| `format` | enum | `Slack`, `Teams`, `Email`, `Webhook`, or `Json`. Signals delivery payload structure. | +| `description` | string? | Optional operator note. | +| `metadata` | map | Sorted map for automation (layout hints, fallback text). | +| `createdBy`/`createdAt` | string?, instant | Auto-populated. | +| `updatedBy`/`updatedAt` | string?, instant | Auto-populated. | +| `schemaVersion` | string | Auto-upgraded on persistence. | + +Templates are normalised: string fields trimmed, locale lower-cased, metadata sorted to preserve determinism. + +--- + +## 3. Variables, helpers, and context + +Templates receive a structured context derived from the Notify event, rule match, and rendering metadata. + +| Path | Description | +|------|-------------| +| `event.*` | Canonical event envelope (`kind`, `tenant`, `ts`, `actor`). | +| `event.scope.*` | Namespace, repository, digest, image, component identifiers, labels, attributes. | +| `payload.*` | Raw event payload (e.g., `payload.verdict`, `payload.delta.*`, `payload.links.*`). | +| `rule.*` | Rule descriptor (`ruleId`, `name`, `labels`, `metadata`). | +| `action.*` | Action descriptor (`actionId`, `channel`, `digest`, `throttle`, `metadata`). | +| `policy.*` | Policy metadata when supplied (`revisionId`, `name`). | +| `topFindings[]` | Top-N findings summarised for convenience (vulnerability ID, severity, reachability). | +| `digest.*` | When rendering digest flushes: `window`, `openedAt`, `itemCount`. | + +Built-in helpers mirror the architecture dossier: + +| Helper | Usage | +|--------|-------| +| `severity_icon severity` | Returns emoji/text badge representing severity. | +| `link text url` | Produces channel-safe hyperlink. | +| `pluralize count "finding"` | Adds plural suffix when `count != 1`. | +| `truncate text maxLength` | Cuts strings while preserving determinism. | +| `code text` | Formats inline code (Markdown/HTML aware). | + +Connectors may expose additional helpers via partials, but must remain deterministic and side-effect free. + +--- + +## 4. Sample templates + +### 4.1 Slack (Markdown + block kit) + +```hbs +{{#*inline "findingLine"}} +- {{severity_icon severity}} {{vulnId}} ({{severity}}) in `{{component}}` +{{/inline}} + +*:rotating_light: {{payload.summary.total}} findings {{#if payload.delta.newCritical}}(new critical: {{payload.delta.newCritical}}){{/if}}* + +{{#if topFindings.length}} +Top findings: +{{#each topFindings}}{{> findingLine}}{{/each}} +{{/if}} + +{{link "Open report in Console" payload.links.ui}} +``` + +### 4.2 Email (HTML + text alternative) + +```hbs +

{{payload.verdict}} for {{event.scope.repo}}

+

{{payload.summary.total}} findings ({{payload.summary.blocked}} blocked, {{payload.summary.warned}} warned)

+ + + + {{#each topFindings}} + + + + + + {{/each}} + +
FindingSeverityPackage
{{this.vulnId}}{{this.severity}}{{this.component}}
+

{{link "View full analysis" payload.links.ui}}

+``` + +When delivering via email, connectors automatically attach a plain-text alternative derived from the rendered content to preserve accessibility. + +--- + +## 5. Preview and validation + +- `POST /channels/{id}/test` accepts an optional `templateId` and sample payload to produce a rendered preview without dispatching the event. Results include channel type, target, title/summary, locale, body hash, and connector metadata. +- UI previews rely on the same API and highlight connector fallbacks (e.g., Teams adaptive card vs. text fallback). +- Offline Kit scenarios can call `/internal/notify/templates/normalize` to ensure bundled templates match the canonical schema before packaging. + +--- + +## 6. Best practices + +- Keep channel-specific limits in mind (Slack block/character quotas, Teams adaptive card size, email line length). Lean on digests to summarise long lists. +- Provide locale-specific versions for high-volume tenants; Notify selects the closest locale, falling back to `en-us`. +- Store connector-specific hints (`metadata.layout`, `metadata.emoji`) in template metadata rather than rules when they affect rendering. +- Version template bodies through metadata (e.g., `metadata.revision: "2025-10-28"`) so tenants can track changes over time. +- Run test previews whenever introducing new helpers to confirm body hashes remain stable across environments. + +--- + +> **Imposed rule reminder:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/observability/observability.md b/docs/observability/observability.md index 5794e80c..8084f267 100644 --- a/docs/observability/observability.md +++ b/docs/observability/observability.md @@ -3,7 +3,7 @@ > **Audience:** Observability Guild, Concelier/Excititor SREs, platform operators. > **Scope:** Metrics, traces, logs, dashboards, and runbooks introduced as part of the Aggregation-Only Contract (AOC) rollout (Sprint 19). -This guide captures the canonical signals emitted by Concelier and Excititor once AOC guards are active. It explains how to consume the metrics in dashboards, correlate traces/logs for incident triage, and operate in offline environments. Pair this guide with the [AOC reference](../ingestion/aggregation-only-contract.md) and [architecture overview](../architecture/overview.md). +This guide captures the canonical signals emitted by Concelier and Excititor once AOC guards are active. It explains how to consume the metrics in dashboards, correlate traces/logs for incident triage, and operate in offline environments. Pair this guide with the [AOC reference](../ingestion/aggregation-only-contract.md) and [architecture overview](../modules/platform/architecture-overview.md). --- @@ -118,11 +118,11 @@ Update `docs/assets/dashboards/` with screenshots when Grafana capture pipeline ## 7 · References - [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) -- [Architecture overview](../architecture/overview.md) +- [Architecture overview](../modules/platform/architecture-overview.md) - [Console AOC dashboard](../ui/console.md) - [CLI AOC commands](../cli/cli-reference.md) -- [Concelier architecture](../ARCHITECTURE_CONCELIER.md) -- [Excititor architecture](../ARCHITECTURE_EXCITITOR.md) +- [Concelier architecture](../modules/concelier/architecture.md) +- [Excititor architecture](../modules/excititor/architecture.md) - [Scheduler Worker observability guide](../ops/scheduler-worker-operations.md) --- diff --git a/docs/policy/overview.md b/docs/policy/overview.md index 7790c29b..276df065 100644 --- a/docs/policy/overview.md +++ b/docs/policy/overview.md @@ -141,7 +141,7 @@ All modes are cancellation-aware and checkpoint progress for replay in case of d - **Authority scopes:** Gateway enforces `policy:read`, `policy:write`, `policy:simulate`, `policy:runs`, `findings:read`, `effective:write`. Service identities must present DPoP-bound tokens. - **Tenant isolation:** Collections partition by tenant identifier; cross-tenant queries require explicit admin scopes and return audit warnings. -- **Sealed mode:** In air-gapped deployments the engine surfaces `sealed=true` hints in explain traces, warning about cached EPSS/KEV data and suggesting bundle refreshes (see `docs/airgap/EPIC_16_AIRGAP_MODE.md` §3.7). +- **Sealed mode:** In air-gapped deployments the engine surfaces `sealed=true` hints in explain traces, warning about cached EPSS/KEV data and suggesting bundle refreshes (see `docs/airgap/airgap-mode.md`). - **Observability:** Structured logs carry correlation IDs matching orchestrator job IDs; metrics integrate with OpenTelemetry exporters; sampled rule-hit logs redact policy secrets. - **Incident response:** Incident mode can be forced via API, boosting trace retention and notifying Notifier through `policy.incident.activated` events. diff --git a/docs/risk/EPIC_18_RISK_PROFILES.md b/docs/risk/EPIC_18_RISK_PROFILES.md deleted file mode 100644 index 8ca147c0..00000000 --- a/docs/risk/EPIC_18_RISK_PROFILES.md +++ /dev/null @@ -1,260 +0,0 @@ -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. - ---- - -# Epic 18: Risk Scoring Profiles - -**Short name:** Risk Profiles -**Primary components:** Policy Engine, Findings Ledger, Conseiller (Feedser), Excitator (VEXer), StellaOps Console, Policy Studio, CLI, Export Center, Authority & Tenancy, Observability -**Surfaces:** policy documents, scoring engine, factor providers, explainability artifacts, APIs, CLI, UI - -**AOC ground rule reminder:** Conseiller and Excitator aggregate and link advisories/VEX. They never merge or mutate source records. Risk scoring consumes linked items and computes a contextual score per finding and per asset without collapsing sources; provenance is preserved and shown. - ---- - -## 1) What it is - -Risk Scoring Profiles let users define, version and apply customizable formulas that turn raw signals (CVSS, EPSS‑like exploit likelihood, KEV‑style exploited lists, VEX status, reachability, runtime evidence, fix availability, asset criticality, provenance trust, etc.) into a single normalized risk score from 0 to 100 with severity buckets. Profiles are authored in Policy Studio, attached to scopes/tenants/projects, simulated against inventories and SBOMs, and executed by a scoring engine that outputs: - -* A final score and severity. -* A factor‑by‑factor contribution breakdown with math. -* Gating decisions (e.g., VEX “not affected” forces score to 0). -* Audit and provenance for every signal used. - -Profiles can differ by environment: “Exploit‑aware prod,” “Compliance‑focused,” “Safety‑critical,” “Dev velocity,” and so on. The engine is pluggable: new signals can be added without breaking existing profiles. - ---- - -## 2) Why - -* One size doesn’t fit anyone. Different orgs weigh exploitability vs business criticality differently. -* Reduce noise and accelerate triage by aligning scores with how teams actually make decisions. -* Make risk explainable. If a score says 86, show why. -* Enable policy‑aware flows elsewhere: gates, notifications, dashboards, remediation queues. - ---- - -## 3) How it should work - -### 3.1 Core model - -A **RiskProfile** defines: - -* **Metadata:** name, version, description, owner, scope selector, status (draft/published/deprecated). -* **Signals:** named inputs with source bindings and transforms. -* **Formula:** a composition of weighted terms, caps, gates, and overrides producing a 0‑100 score. -* **Severity mapping:** score→{Critical, High, Medium, Low, None}. -* **Gates:** hard conditions that short‑circuit scoring (e.g., VEX Not Affected → 0). -* **Overrides:** explicit per‑package/per‑CVE/per‑asset adjustments with audit. -* **Explainability:** must compute contribution of each term and include raw values. -* **Versioning:** immutable content hash, `profile_id@version`. Inheritance supported via `extends`. - -### 3.2 Signals (factor) catalog - -Initial signals supported out of the box: - -| Signal | Description | Expected range | Default transform | -| ---------------------- | ------------------------------------------------ | -------------- | -------------------- | -| `cvss_base` | CVSS base score from each advisory | 0..10 | linear: `x/10` | -| `epss_like` | Exploit likelihood (0..1) | 0..1 | identity | -| `kev_flag` | Known exploited in the wild (boolean) | {0,1} | step: 0 or 1 | -| `vex_status` | VEX: affected, not_affected, under_investigation | enum | gate + multiplier | -| `reachability` | Static reachability to vulnerable code path | 0..1 | identity | -| `runtime_evidence` | Runtime evidence of vulnerable symbol/path | 0..1 | identity | -| `internet_exposed` | Asset externally reachable | {0,1} | multiplier | -| `asset_criticality` | Business criticality of asset | 1..5 | normalize: `(x-1)/4` | -| `fix_available` | Patch or upgrade exists | {0,1} | negative weight | -| `age_days` | Days since advisory published | 0..∞ | logistic decay | -| `privilege_escalation` | Elevation potential | {0,1} | positive bump | -| `rce_flag` | Remote code execution | {0,1} | positive bump | -| `provenance_trust` | Signature/provenance (SLSA‑ish) | 0..1 | inverse weight | -| `pkg_popularity` | Package ecosystem usage | 0..1 | mild bump | -| `source_consensus` | Count of agreeing sources (Conseiller‑linked) | 1..N | saturating transform | - -Notes: - -* Conseiller can link multiple advisories per CVE. Signals like `cvss_base` and `kev_flag` are aggregated via declared **reducers**: `max`, `mean`, or **consensus** (e.g., count of sources claiming exploited). - -### 3.3 Formula template - -Default formula (normalized result 0..1 before scaling to 0..100): - -``` -score = - gate(VEX_not_affected => 0) * - clamp01( - w1*cvss' - + w2*epss' - + w3*reachability' - + w4*runtime_evidence' - + w5*internet_exposed' - + w6*asset_criticality' - + w7*kev_flag' - + w8*rce_flag' - + w9*privilege_escalation' - + w10*source_consensus' - + w11*(1 - provenance_trust') - + w12*(1 - fix_available') - + w13*age_decay' - + bias - ) -``` - -* Each term is a transformed, normalized signal (denoted `'`). -* Weights default to reasonable values (e.g., cvss 0.25, epss 0.2, reachability 0.1, runtime 0.1, internet_exposed 0.08, asset_criticality 0.08, kev 0.07, rce 0.04, priv_esc 0.03, consensus 0.03, provenance inverse 0.01, fix inverse 0.005, age 0.005). -* **Severity mapping (default):** - - * Critical ≥ 85 - * High 70–84 - * Medium 40–69 - * Low 15–39 - * None < 15 - -Profiles can override weights, gating, transforms and severity thresholds. - -### 3.4 Reducers and provenance - -For signals with multiple sources: - -* `cvss_base`: default reducer `max`. -* `kev_flag`: reducer `any`. -* `epss_like`: reducer `max`. -* `vex_status`: **gate precedence:** if any linked VEX says `not_affected`, apply gate 0 unless an explicit policy disables that source; otherwise, most conservative status wins (`affected` > `under_investigation` > `unknown`). -* Every reduction lists contributing sources in the explanation with their digests. - -### 3.5 Explainability artifact - -For every scored item, produce a JSON object: - -```json -{ - "profile_id": "risk-default", - "profile_version": "1.2.0", - "input": { "asset_id": "...", "package": "openssl@1.1.1u", "cve": "CVE-XXXX-YYYY" }, - "signals": { - "cvss_base": { "values": [{"source":"nvd","value":9.8}, {"source":"vendor","value":9.1}], "reducer":"max", "reduced":9.8, "normalized":0.98 }, - "epss_like": { "value":0.72, "normalized":0.72 }, - "vex_status": { "values":[{"source":"vendor","value":"affected"}], "decision":"affected" } - }, - "formula": { - "weights": { "cvss":0.25, "epss":0.20 }, - "gates": [{ "name":"VEX_not_affected", "applied": false }] - }, - "contributions": [ - { "signal":"cvss_base", "weight":0.25, "value":0.98, "contribution":24.5 }, - { "signal":"epss_like", "weight":0.20, "value":0.72, "contribution":14.4 } - ], - "score": 87.1, - "severity": "Critical", - "provenance": { "calculated_at":"2025-10-25T12:00:00Z", "engine":"risk-engine@v0.6.3", "trace_id":"..." } -} -``` - -### 3.6 Profile scoping and inheritance - -* Profiles attach to scopes via Authority & Tenancy: org/tenant/project/environment. -* A scope resolves **one active profile** by precedence: project > environment > org default. -* Profiles may `extends` a base profile, overriding weights and thresholds. Resolve via immutable parent chain. - -### 3.7 Execution path - -1. New or updated findings arrive from Conseiller/Excitator into Findings Ledger. -2. A **Scoring Job** is enqueued per scope with a batch of items. -3. The engine pulls necessary signals via **Factor Providers** (reachability, runtime, KEV lists, etc.). -4. The formula executes; results are upserted to Findings Ledger with an explainability blob pointer. -5. Notifications Studio triggers based on severity deltas. -6. Console and CLI read scored findings; filters and charts operate on score and severity. - -### 3.8 Factor Provider interface - -``` -interface FactorProvider { - id(): string; - requiredInputs(): string[]; - fetch(ctx, inputs[]): Promise>; -} -``` - -Providers must be deterministic and cacheable. Every factor has a TTL and a backfill policy. - -### 3.9 Simulation - -Policy Studio provides “Simulate with profile” functionality to test profiles against SBOMs or asset sets. Simulation outputs include distributions, severity shifts, and top movers, and can be exported. - -### 3.10 Air‑gapped behavior - -Profiles work offline; providers rely on bundled datasets produced by Export Center. Missing providers surface explicit gaps in explanations. - ---- - -## 4) Architecture - -### 4.1 New modules - -* `src/RiskEngine/StellaOps.RiskEngine/` -* `src/RiskEngine/StellaOps.RiskEngine/providers/` -* `src/Policy/StellaOps.Policy.RiskProfile/` -* Database migrations for profiles/results/explanations -* `src/UI/StellaOps.UI` -* `src/Cli/StellaOps.Cli` -* `src/ExportCenter/StellaOps.ExportCenter.RiskBundles` - -### 4.2 Data model - -Tables for `risk_profiles`, `scoring_jobs`, `scoring_results`, `explanations` with indexes on finding keys, scope, severity, and timestamps. - ---- - -## 5) APIs and contracts - -Endpoints include profile CRUD, publish, simulate, job enqueue, results queries, explanation retrieval, and schema discovery. Authentication scopes: `risk.profile:*`, `risk.result:read`, `risk.job:write`. - ---- - -## 6) Documentation changes - -List of required docs with banner statements covering overview, profiles, factors, formulas, explainability, API, console UI, CLI commands, air-gapped bundles, and AOC invariants. - ---- - -## 7) Implementation plan - -Seven phases: foundations, storage/APIs, Console & Policy Studio, CLI & SDKs, expanded factors, air-gapped support, quality/performance. - ---- - -## 8) Engineering tasks - -Detailed task list spanning schema, engine, providers, APIs, ledger integration, console, CLI, export center, observability, docs, and testing. - ---- - -## 9) Feature changes required in other components - -Defines cross-team expectations for Conseiller, Excitator, Findings Ledger, Policy Studio, Vulnerability Explorer, SBOM Graph Explorer, Notifications, Authority, Export Center, CLI & SDKs. - ---- - -## 10) Acceptance criteria - -Coverage of authoring, simulation, scoring, UI, CLI, air-gapped support, AOC invariants, and performance. - ---- - -## 11) Risks and mitigations - -Addresses signal drift, weight overfitting, performance, VEX trust, and compliance differences. - ---- - -## 12) Philosophy - -Principles: context, explainability, truth preservation, portability, and loud failures. - ---- - -## 13) Example profile - -Contains an abbreviated YAML example demonstrating schema usage, weights, gates, severity mapping, and overrides. - -> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. diff --git a/docs/risk/risk-profiles.md b/docs/risk/risk-profiles.md new file mode 100644 index 00000000..949d34bc --- /dev/null +++ b/docs/risk/risk-profiles.md @@ -0,0 +1,57 @@ +# Risk Scoring Profiles + +> Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied. + +## Overview + +Risk Scoring Profiles define customizable formulas that convert raw evidence (CVSS, EPSS-like exploit likelihood, KEV exploited lists, VEX status, reachability, runtime evidence, fix availability, asset criticality, provenance trust) into normalized risk scores (0–100) with severity buckets. Profiles are authored in Policy Studio, simulated, versioned, and executed by the scoring engine with full explainability. + +- **Primary components:** Policy Engine, Findings Ledger, Conseiller, Excitator, Console, Policy Studio, CLI, Export Center, Authority & Tenancy, Observability. +- **Surfaces:** policy documents, scoring engine, factor providers, explainability artefacts, APIs, CLI, UI. + +Aggregation-Only Contract remains in force: Conseiller and Excitator never merge or mutate source records. Risk scoring consumes linked evidence and preserves provenance for explainability. + +## Core workflow + +1. **Profile authoring:** Policy Studio exposes declarative DSL to define factors, weights, thresholds, and severity buckets. +2. **Simulation:** operators preview profiles against historical findings/SBOMs, compare with existing policies, and inspect factor breakdowns. +3. **Activation:** Policy Engine evaluates profiles on change streams, producing scores and detailed factor contributions per finding and per asset. +4. **Explainability:** CLI/Console display math traces, provenance IDs, and rationale for each factor. Export Center packages reports for auditors. +5. **Versioning:** profiles carry semantic versions, promotion workflows, and rollback hooks; Authority scopes enforce who can publish or edit. + +## Factor model + +| Factor | Description | Typical signal source | +| --- | --- | --- | +| Exploit likelihood | EPSS/KEV or internal intel | Conseiller enrichment | +| VEX status | not_affected / affected / fixed | Excitator (VEX Lens) | +| Reachability | entrypoint closure, runtime observations | Scanner + Zastava | +| Fix availability | patch released, vendor guidance | Conseiller, Policy Engine | +| Asset criticality | business context, tenant overrides | Policy Studio inputs | +| Provenance trust | signed evidence, attestation status | Attestor, Authority | + +Factors feed into a weighted scoring engine with per-factor contribution reporting. + +## Governance & guardrails + +- Profiles live in Policy Studio with draft/review/approval workflows. +- Policy Engine enforces deterministic evaluation; simulations and production runs share the same scoring code. +- CLI parity enables automated promotion, export/import, and simulation from pipelines. +- Observability records scoring latency, factor distribution, and profile usage. +- Offline support: profiles, factor plugins, and explain bundles ship inside mirror bundles for air-gapped environments. + +## Deliverables + +- Policy language reference and examples. +- Simulation APIs/CLI with diff output. +- Scoring engine implementation with explain traces and determinism checks. +- Console visualizations (severity heatmaps, contribution waterfalls). +- Export Center reports with risk scoring sections. +- Observability dashboards for profile health and scoring throughput. + +## References + +- Policy core: `docs/modules/policy/architecture.md` +- Findings ledger: `docs/modules/vuln-explorer/architecture.md` +- VEX consensus: `docs/modules/vex-lens/architecture.md` +- Offline operations: `docs/airgap/airgap-mode.md` diff --git a/docs/security/authority-scopes.md b/docs/security/authority-scopes.md index c7d8def2..c3b065b7 100644 --- a/docs/security/authority-scopes.md +++ b/docs/security/authority-scopes.md @@ -1,261 +1,261 @@ -# Authority Scopes & Tenancy — AOC Update - -> **Audience:** Authority Core, platform security engineers, DevOps owners. -> **Scope:** Scope taxonomy, tenancy enforcement, rollout guidance for the Aggregation-Only Contract (Sprint 19). - -Authority issues short-lived tokens bound to tenants and scopes. Sprint 19 introduces new scopes to support the AOC guardrails in Concelier and Excititor. This document lists the canonical scope catalogue, describes tenancy propagation, and outlines operational safeguards. - ---- - -## 1 · Scope catalogue (post AOC) - -| Scope | Surface | Purpose | Notes | -|-------|---------|---------|-------| -| `advisory:ingest` | Concelier ingestion APIs | Append-only writes to `advisory_raw` collections. | Requires tenant claim; blocked for global clients. | -| `advisory:read` | `/aoc/verify`, Concelier dashboards, CLI | Read-only access to stored advisories and guard results. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. | -| `vex:ingest` | Excititor ingestion APIs | Append-only writes to `vex_raw`. | Mirrors `advisory:ingest`; tenant required. | -| `vex:read` | `/aoc/verify`, Excititor dashboards, CLI | Read-only access to stored VEX material. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. | -| `aoc:verify` | CLI/CI pipelines, Console verification jobs | Execute Aggregation-Only Contract guard runs. | Always issued with tenant; required whenever requesting `advisory:read`, `vex:read`, or any `signals:*` scope. | -| `signals:read` | Signals API, reachability dashboards | Read-only access to stored reachability signals. | Tenant and `aoc:verify` required; missing pairing returns `invalid_scope`. | -| `signals:write` | Signals ingestion APIs | Append-only writes for reachability signals. | Requires tenant and `aoc:verify`; Authority logs `authority.aoc_scope_violation` on mismatch. | -| `signals:admin` | Signals administration tooling | Rotate credentials, manage reachability sensors, purge stale data. | Reserved for automation; `aoc:verify` + tenant mandatory; violations are audited. | -| `graph:write` | Cartographer pipeline | Enqueue graph build/overlay jobs. | Reserved for Cartographer service identity; tenant required. | -| `graph:read` | Graph API, Scheduler overlays, UI | Read graph projections/overlays. | Tenant required; granted to Cartographer, Graph API, Scheduler. | -| `graph:export` | Graph export endpoints | Stream GraphML/JSONL artefacts. | UI/gateway automation only; tenant required. | -| `graph:simulate` | Policy simulation overlays | Trigger what-if overlays on graphs. | Restricted to automation; tenant required. | -| `effective:write` | Policy Engine | Create/update `effective_finding_*` collections. | **Only** the Policy Engine service client may hold this scope; tenant required. | -| `findings:read` | Console, CLI, exports | Read derived findings materialised by Policy Engine. | Shared across tenants with RBAC; tenant claim still enforced. | -| `policy:author` | Policy Studio (Console, CLI) | Author drafts, run lint, execute quick simulations. | Tenant required; typically granted via `role/policy-author`. | -| `policy:review` | Policy Studio review panes | Review drafts, leave comments, request changes. | Tenant required; pair with `policy:simulate` for diff previews. | -| `policy:approve` | Policy Studio approvals | Approve or reject policy drafts. | Tenant required; fresh-auth enforced by Console UI. | -| `policy:operate` | Policy Studio promotion controls | Trigger batch simulations, promotions, and canary runs. | Tenant required; combine with `policy:run`/`policy:activate`. | -| `policy:audit` | Policy audit exports | Access immutable policy history, comments, and signatures. | Tenant required; read-only access. | -| `policy:simulate` | Policy Studio / CLI simulations | Run simulations against tenant inventories. | Tenant required; available to authors, reviewers, operators. | -| `vuln:read` | Vuln Explorer API/UI | Read normalized vulnerability data. | Tenant required. | -| `export.viewer` | Export Center APIs | List export profiles/runs, fetch manifests and bundles. | Tenant required; read-only access. | -| `export.operator` | Export Center APIs | Trigger export runs, manage schedules, request verifications. | Tenant required; pair with `export.admin` for retention/encryption changes. | -| `export.admin` | Export Center administrative APIs | Configure retention policies, encryption keys, and scheduling defaults. | Tenant required; token requests must include `export_reason` + `export_ticket`; Authority audits denials. | -| `orch:read` | Orchestrator dashboards/API | Read queued jobs, worker state, and rate-limit telemetry. | Tenant required; never grants mutation rights. | -| `orch:operate` | Orchestrator control actions | Execute pause/resume, retry, sync-now, and backfill operations. Requires tenant assignment **and** `operator_reason`/`operator_ticket` parameters when requesting tokens. | -| `exceptions:read` | Exception service APIs, Console | Enumerate exception definitions, routing templates, and approval state. | Tenant and approval routing metadata required for audit replay. | -| `exceptions:write` | Policy Engine → Authority bridge | Persist exception evaluations, lifecycle events, and status changes. | Tenant required; only service principals should hold this scope. | -| `exceptions:approve` | Console fresh-auth flows, delegated admins | Approve or reject exception requests routed through Authority. | Tenant required; Authority enforces MFA when any bound routing template has `requireMfa=true`. | -| `ui.read` | Console base APIs | Retrieve tenant catalog, profile metadata, and token introspection results. | Tenant header required; responses are DPoP-bound and audit logged. | -| `authority:tenants.read` | Console admin workspace | Enumerate configured tenants, default roles, and isolation metadata. | Tenant claim must match header; access audited via `authority.console.tenants.read`. | -| Existing scopes | (e.g., `policy:*`, `concelier.jobs.trigger`) | Unchanged. | `concelier.merge` is retired — clients must request `advisory:ingest`/`advisory:read`; requests continue to fail with `invalid_client`. Review `/docs/security/policy-governance.md` for policy-specific scopes. | - -### 1.1 Scope bundles (roles) - -- **`role/concelier-ingest`** → `advisory:ingest`, `advisory:read`. -- **`role/excititor-ingest`** → `vex:ingest`, `vex:read`. -- **`role/signals-uploader`** → `signals:write`, `signals:read`, `aoc:verify`. -- **`role/aoc-operator`** → `aoc:verify`, `advisory:read`, `vex:read`. -- **`role/policy-engine`** → `effective:write`, `findings:read`. -- **`role/cartographer-service`** → `graph:write`, `graph:read`. -- **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`. -- **`role/console`** → `ui.read`, `advisory:read`, `vex:read`, `exceptions:read`, `aoc:verify`, `findings:read`, `orch:read`, `vuln:read`. -- **`role/ui-console-admin`** → `ui.read`, `authority:tenants.read`, `authority:roles.read`, `authority:tokens.read`, `authority:clients.read` (paired with write scopes where required). -- **`role/orch-viewer`** *(Authority role: `Orch.Viewer`)* → `orch:read`. -- **`role/orch-operator`** *(Authority role: `Orch.Operator`)* → `orch:read`, `orch:operate`. -- **`role/policy-author`** → `policy:author`, `policy:read`, `policy:simulate`, `findings:read`. -- **`role/policy-reviewer`** → `policy:review`, `policy:read`, `policy:simulate`, `findings:read`. -- **`role/policy-approver`** → `policy:approve`, `policy:review`, `policy:read`, `policy:simulate`, `findings:read`. -- **`role/policy-operator`** → `policy:operate`, `policy:run`, `policy:activate`, `policy:read`, `policy:simulate`, `findings:read`. -- **`role/policy-auditor`** → `policy:audit`, `policy:read`, `policy:simulate`, `findings:read`. -- **`role/export-viewer`** *(Authority role: `Export.Viewer`)* → `export.viewer`. -- **`role/export-operator`** *(Authority role: `Export.Operator`)* → `export.viewer`, `export.operator`. -- **`role/export-admin`** *(Authority role: `Export.Admin`)* → `export.viewer`, `export.operator`, `export.admin`. -- **`role/exceptions-service`** → `exceptions:read`, `exceptions:write`. -- **`role/exceptions-approver`** → `exceptions:read`, `exceptions:approve`. - -Roles are declared per tenant in `authority.yaml`: - -```yaml -tenants: - - name: default - roles: - concelier-ingest: - scopes: [advisory:ingest, advisory:read] - signals-uploader: - scopes: [signals:write, signals:read, aoc:verify] - aoc-operator: - scopes: [aoc:verify, advisory:read, vex:read] - orch-viewer: - scopes: [orch:read] - orch-operator: - scopes: [orch:read, orch:operate] - policy-author: - scopes: [policy:author, policy:read, policy:simulate, findings:read] - policy-reviewer: - scopes: [policy:review, policy:read, policy:simulate, findings:read] - policy-approver: - scopes: [policy:approve, policy:review, policy:read, policy:simulate, findings:read] - policy-operator: - scopes: [policy:operate, policy:run, policy:activate, policy:read, policy:simulate, findings:read] - policy-auditor: - scopes: [policy:audit, policy:read, policy:simulate, findings:read] - policy-engine: - scopes: [effective:write, findings:read] - exceptions-service: - scopes: [exceptions:read, exceptions:write] - exceptions-approver: - scopes: [exceptions:read, exceptions:approve] -``` - -> **MFA requirement:** When any `exceptions.routingTemplates` entry sets `requireMfa: true`, Authority refuses to mint tokens containing `exceptions:approve` unless the authenticating identity provider advertises MFA support. Password/OIDC flows produce `authority.password.grant` audit events with `reason="Exception approval scope requires an MFA-capable identity provider."` when the requirement is violated. - ---- - -## 2 · Tenancy enforcement - -### 2.1 Token claims - -Tokens now include: - -- `tenant` claim (string) — required for all ingestion and verification scopes. -- `service_identity` (optional) — e.g., `policy-engine`, `cartographer`. Required when requesting `effective:write` or `graph:write`. -- `delegation_allowed` (boolean) — defaults `false`. Prevents console tokens from delegating ingest scopes. - -Authority rejects requests when: - -- `tenant` is missing while requesting `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, or `aoc:verify` scopes. -- `aoc:verify` is absent while tokens request `advisory:read`, `vex:read`, or any `signals:*` scope (`invalid_scope` with deterministic message). -- `service_identity != policy-engine` but `effective:write` is present (`ERR_AOC_006` enforcement). -- `service_identity != cartographer` but `graph:write` is present (graph pipeline enforcement). -- Tokens attempt to combine `advisory:ingest` with `effective:write` (separation of duties). -- `exceptions:approve` is requested by a client without a tenant assignment or via an identity provider lacking MFA when `RequireMfaForApprovals=true`. - -### 2.2 Propagation - -- API Gateway forwards `tenant` claim as header (`X-Stella-Tenant`). Services refuse requests lacking the header. -- Concelier/Excititor stamp tenant into raw documents and structured logs. -- Policy Engine copies `tenant` from tokens into `effective_finding_*` collections. -- Exception lifecycle services persist tenant and the selected routing template identifier alongside approval decisions. Authority audit events (`authority.password.grant`, `authority.client_credentials.grant`) surface `audit.scopes` and, on denials, a `scope.invalid` metadata entry so operators can trace exception approval attempts without inspecting downstream services. - -### 2.3 Cross-tenant scenarios - -- Platform operators with `tenant:admin` can assume other tenants via `/authority/tenant/switch` if explicitly permitted. -- CLI commands accept `--tenant ` to override environment default; Authority logs tenant switch events (`authority.tenant.switch`). -- Console tenant picker uses delegated token exchange (`/token/exchange`) to obtain scoped tenant tokens without exposing raw credentials. - ---- - -## 3 · Configuration changes - -### 3.1 Authority configuration (`authority.yaml`) - -Add new scopes and optional claims transformations: - -```yaml -security: - scopes: - - name: advisory:ingest - description: Concelier raw ingestion (append-only) - - name: advisory:read - description: Read Concelier advisories and guard verdicts - - name: vex:ingest - description: Excititor raw ingestion - - name: vex:read - description: Read Excititor VEX records - - name: aoc:verify - description: Run AOC verification - - name: effective:write - description: Policy Engine materialisation - - name: findings:read - description: Read derived findings - - name: graph:write - description: Cartographer build submissions - - name: graph:read - description: Read graph overlays - - name: graph:export - description: Export graph artefacts - - name: graph:simulate - description: Run graph what-if simulations - - name: vuln:read - description: Read Vuln Explorer data - claimTransforms: - - match: { scope: "effective:write" } - require: - serviceIdentity: policy-engine - - match: { scope: "graph:write" } - require: - serviceIdentity: cartographer -``` - -### 3.2 Client registration - -Update service clients: - -- `Concelier.WebService` → request `advisory:ingest`, `advisory:read`. -- `Excititor.WebService` → request `vex:ingest`, `vex:read`. -- `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`. -- `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`. -- `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required. -- `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read` plus existing UI scopes. -- `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed. - -Client definition snippet: - -```yaml -clients: - - clientId: concelier-web - grantTypes: [client_credentials] - scopes: [advisory:ingest, advisory:read] - tenants: [default] - - clientId: policy-engine - grantTypes: [client_credentials] - scopes: [effective:write, findings:read] - properties: - serviceIdentity: policy-engine - - clientId: cartographer-service - grantTypes: [client_credentials] - scopes: [graph:write, graph:read] - properties: - serviceIdentity: cartographer -``` - ---- - -## 4 · Operational safeguards - -- **Audit events:** Authority emits `authority.scope.granted` and `authority.scope.revoked` events with `scope` and `tenant`. Monitor for unexpected grants. -- **Rate limiting:** Apply stricter limits on `/token` endpoints for clients requesting `advisory:ingest` or `vex:ingest` to mitigate brute-force ingestion attempts. -- **Incident response:** Link AOC alerts to Authority audit logs to confirm whether violations come from expected identities. -- **Rotation:** Rotate ingest client secrets alongside guard deployments; add rotation steps to `ops/authority-key-rotation.md`. -- **Testing:** Integration tests must fail if tokens lacking `tenant` attempt ingestion; add coverage in Concelier/Excititor smoke suites (see `CONCELIER-CORE-AOC-19-013`). - ---- - -## 5 · Offline & air-gap notes - -- Offline Kit bundles include tenant-scoped service credentials. Ensure ingest bundles ship without `advisory:ingest` scopes unless strictly required. -- CLI verification in offline environments uses pre-issued `aoc:verify` tokens; document expiration and renewal processes. -- Authority replicas in air-gapped environments should restrict scope issuance to known tenants and log all `/token` interactions for later replay. - ---- - -## 6 · References - -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) -- [Architecture overview](../architecture/overview.md) -- [Concelier architecture](../ARCHITECTURE_CONCELIER.md) -- [Excititor architecture](../ARCHITECTURE_EXCITITOR.md) -- [Policy governance](policy-governance.md) -- [Authority key rotation playbook](../ops/authority-key-rotation.md) - ---- - -## 7 · Compliance checklist - -- [ ] Scope catalogue updated in Authority configuration templates. -- [ ] Role mappings documented for each tenant profile. -- [ ] Claim transforms enforce `serviceIdentity` for `effective:write`. -- [ ] Claim transforms enforce `serviceIdentity` for `graph:write`. -- [ ] Concelier/Excititor smoke tests cover missing tenant rejection. -- [ ] Offline kit credentials reviewed for least privilege. -- [ ] Audit/monitoring guidance validated with Observability Guild. -- [ ] Authority Core sign-off recorded (owner: @authority-core, due 2025-10-28). - ---- - -*Last updated: 2025-10-27 (Sprint 19).* +# Authority Scopes & Tenancy — AOC Update + +> **Audience:** Authority Core, platform security engineers, DevOps owners. +> **Scope:** Scope taxonomy, tenancy enforcement, rollout guidance for the Aggregation-Only Contract (Sprint 19). + +Authority issues short-lived tokens bound to tenants and scopes. Sprint 19 introduces new scopes to support the AOC guardrails in Concelier and Excititor. This document lists the canonical scope catalogue, describes tenancy propagation, and outlines operational safeguards. + +--- + +## 1 · Scope catalogue (post AOC) + +| Scope | Surface | Purpose | Notes | +|-------|---------|---------|-------| +| `advisory:ingest` | Concelier ingestion APIs | Append-only writes to `advisory_raw` collections. | Requires tenant claim; blocked for global clients. | +| `advisory:read` | `/aoc/verify`, Concelier dashboards, CLI | Read-only access to stored advisories and guard results. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. | +| `vex:ingest` | Excititor ingestion APIs | Append-only writes to `vex_raw`. | Mirrors `advisory:ingest`; tenant required. | +| `vex:read` | `/aoc/verify`, Excititor dashboards, CLI | Read-only access to stored VEX material. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. | +| `aoc:verify` | CLI/CI pipelines, Console verification jobs | Execute Aggregation-Only Contract guard runs. | Always issued with tenant; required whenever requesting `advisory:read`, `vex:read`, or any `signals:*` scope. | +| `signals:read` | Signals API, reachability dashboards | Read-only access to stored reachability signals. | Tenant and `aoc:verify` required; missing pairing returns `invalid_scope`. | +| `signals:write` | Signals ingestion APIs | Append-only writes for reachability signals. | Requires tenant and `aoc:verify`; Authority logs `authority.aoc_scope_violation` on mismatch. | +| `signals:admin` | Signals administration tooling | Rotate credentials, manage reachability sensors, purge stale data. | Reserved for automation; `aoc:verify` + tenant mandatory; violations are audited. | +| `graph:write` | Cartographer pipeline | Enqueue graph build/overlay jobs. | Reserved for Cartographer service identity; tenant required. | +| `graph:read` | Graph API, Scheduler overlays, UI | Read graph projections/overlays. | Tenant required; granted to Cartographer, Graph API, Scheduler. | +| `graph:export` | Graph export endpoints | Stream GraphML/JSONL artefacts. | UI/gateway automation only; tenant required. | +| `graph:simulate` | Policy simulation overlays | Trigger what-if overlays on graphs. | Restricted to automation; tenant required. | +| `effective:write` | Policy Engine | Create/update `effective_finding_*` collections. | **Only** the Policy Engine service client may hold this scope; tenant required. | +| `findings:read` | Console, CLI, exports | Read derived findings materialised by Policy Engine. | Shared across tenants with RBAC; tenant claim still enforced. | +| `policy:author` | Policy Studio (Console, CLI) | Author drafts, run lint, execute quick simulations. | Tenant required; typically granted via `role/policy-author`. | +| `policy:review` | Policy Studio review panes | Review drafts, leave comments, request changes. | Tenant required; pair with `policy:simulate` for diff previews. | +| `policy:approve` | Policy Studio approvals | Approve or reject policy drafts. | Tenant required; fresh-auth enforced by Console UI. | +| `policy:operate` | Policy Studio promotion controls | Trigger batch simulations, promotions, and canary runs. | Tenant required; combine with `policy:run`/`policy:activate`. | +| `policy:audit` | Policy audit exports | Access immutable policy history, comments, and signatures. | Tenant required; read-only access. | +| `policy:simulate` | Policy Studio / CLI simulations | Run simulations against tenant inventories. | Tenant required; available to authors, reviewers, operators. | +| `vuln:read` | Vuln Explorer API/UI | Read normalized vulnerability data. | Tenant required. | +| `export.viewer` | Export Center APIs | List export profiles/runs, fetch manifests and bundles. | Tenant required; read-only access. | +| `export.operator` | Export Center APIs | Trigger export runs, manage schedules, request verifications. | Tenant required; pair with `export.admin` for retention/encryption changes. | +| `export.admin` | Export Center administrative APIs | Configure retention policies, encryption keys, and scheduling defaults. | Tenant required; token requests must include `export_reason` + `export_ticket`; Authority audits denials. | +| `orch:read` | Orchestrator dashboards/API | Read queued jobs, worker state, and rate-limit telemetry. | Tenant required; never grants mutation rights. | +| `orch:operate` | Orchestrator control actions | Execute pause/resume, retry, sync-now, and backfill operations. Requires tenant assignment **and** `operator_reason`/`operator_ticket` parameters when requesting tokens. | +| `exceptions:read` | Exception service APIs, Console | Enumerate exception definitions, routing templates, and approval state. | Tenant and approval routing metadata required for audit replay. | +| `exceptions:write` | Policy Engine → Authority bridge | Persist exception evaluations, lifecycle events, and status changes. | Tenant required; only service principals should hold this scope. | +| `exceptions:approve` | Console fresh-auth flows, delegated admins | Approve or reject exception requests routed through Authority. | Tenant required; Authority enforces MFA when any bound routing template has `requireMfa=true`. | +| `ui.read` | Console base APIs | Retrieve tenant catalog, profile metadata, and token introspection results. | Tenant header required; responses are DPoP-bound and audit logged. | +| `authority:tenants.read` | Console admin workspace | Enumerate configured tenants, default roles, and isolation metadata. | Tenant claim must match header; access audited via `authority.console.tenants.read`. | +| Existing scopes | (e.g., `policy:*`, `concelier.jobs.trigger`) | Unchanged. | `concelier.merge` is retired — clients must request `advisory:ingest`/`advisory:read`; requests continue to fail with `invalid_client`. Review `/docs/security/policy-governance.md` for policy-specific scopes. | + +### 1.1 Scope bundles (roles) + +- **`role/concelier-ingest`** → `advisory:ingest`, `advisory:read`. +- **`role/excititor-ingest`** → `vex:ingest`, `vex:read`. +- **`role/signals-uploader`** → `signals:write`, `signals:read`, `aoc:verify`. +- **`role/aoc-operator`** → `aoc:verify`, `advisory:read`, `vex:read`. +- **`role/policy-engine`** → `effective:write`, `findings:read`. +- **`role/cartographer-service`** → `graph:write`, `graph:read`. +- **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`. +- **`role/console`** → `ui.read`, `advisory:read`, `vex:read`, `exceptions:read`, `aoc:verify`, `findings:read`, `orch:read`, `vuln:read`. +- **`role/ui-console-admin`** → `ui.read`, `authority:tenants.read`, `authority:roles.read`, `authority:tokens.read`, `authority:clients.read` (paired with write scopes where required). +- **`role/orch-viewer`** *(Authority role: `Orch.Viewer`)* → `orch:read`. +- **`role/orch-operator`** *(Authority role: `Orch.Operator`)* → `orch:read`, `orch:operate`. +- **`role/policy-author`** → `policy:author`, `policy:read`, `policy:simulate`, `findings:read`. +- **`role/policy-reviewer`** → `policy:review`, `policy:read`, `policy:simulate`, `findings:read`. +- **`role/policy-approver`** → `policy:approve`, `policy:review`, `policy:read`, `policy:simulate`, `findings:read`. +- **`role/policy-operator`** → `policy:operate`, `policy:run`, `policy:activate`, `policy:read`, `policy:simulate`, `findings:read`. +- **`role/policy-auditor`** → `policy:audit`, `policy:read`, `policy:simulate`, `findings:read`. +- **`role/export-viewer`** *(Authority role: `Export.Viewer`)* → `export.viewer`. +- **`role/export-operator`** *(Authority role: `Export.Operator`)* → `export.viewer`, `export.operator`. +- **`role/export-admin`** *(Authority role: `Export.Admin`)* → `export.viewer`, `export.operator`, `export.admin`. +- **`role/exceptions-service`** → `exceptions:read`, `exceptions:write`. +- **`role/exceptions-approver`** → `exceptions:read`, `exceptions:approve`. + +Roles are declared per tenant in `authority.yaml`: + +```yaml +tenants: + - name: default + roles: + concelier-ingest: + scopes: [advisory:ingest, advisory:read] + signals-uploader: + scopes: [signals:write, signals:read, aoc:verify] + aoc-operator: + scopes: [aoc:verify, advisory:read, vex:read] + orch-viewer: + scopes: [orch:read] + orch-operator: + scopes: [orch:read, orch:operate] + policy-author: + scopes: [policy:author, policy:read, policy:simulate, findings:read] + policy-reviewer: + scopes: [policy:review, policy:read, policy:simulate, findings:read] + policy-approver: + scopes: [policy:approve, policy:review, policy:read, policy:simulate, findings:read] + policy-operator: + scopes: [policy:operate, policy:run, policy:activate, policy:read, policy:simulate, findings:read] + policy-auditor: + scopes: [policy:audit, policy:read, policy:simulate, findings:read] + policy-engine: + scopes: [effective:write, findings:read] + exceptions-service: + scopes: [exceptions:read, exceptions:write] + exceptions-approver: + scopes: [exceptions:read, exceptions:approve] +``` + +> **MFA requirement:** When any `exceptions.routingTemplates` entry sets `requireMfa: true`, Authority refuses to mint tokens containing `exceptions:approve` unless the authenticating identity provider advertises MFA support. Password/OIDC flows produce `authority.password.grant` audit events with `reason="Exception approval scope requires an MFA-capable identity provider."` when the requirement is violated. + +--- + +## 2 · Tenancy enforcement + +### 2.1 Token claims + +Tokens now include: + +- `tenant` claim (string) — required for all ingestion and verification scopes. +- `service_identity` (optional) — e.g., `policy-engine`, `cartographer`. Required when requesting `effective:write` or `graph:write`. +- `delegation_allowed` (boolean) — defaults `false`. Prevents console tokens from delegating ingest scopes. + +Authority rejects requests when: + +- `tenant` is missing while requesting `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, or `aoc:verify` scopes. +- `aoc:verify` is absent while tokens request `advisory:read`, `vex:read`, or any `signals:*` scope (`invalid_scope` with deterministic message). +- `service_identity != policy-engine` but `effective:write` is present (`ERR_AOC_006` enforcement). +- `service_identity != cartographer` but `graph:write` is present (graph pipeline enforcement). +- Tokens attempt to combine `advisory:ingest` with `effective:write` (separation of duties). +- `exceptions:approve` is requested by a client without a tenant assignment or via an identity provider lacking MFA when `RequireMfaForApprovals=true`. + +### 2.2 Propagation + +- API Gateway forwards `tenant` claim as header (`X-Stella-Tenant`). Services refuse requests lacking the header. +- Concelier/Excititor stamp tenant into raw documents and structured logs. +- Policy Engine copies `tenant` from tokens into `effective_finding_*` collections. +- Exception lifecycle services persist tenant and the selected routing template identifier alongside approval decisions. Authority audit events (`authority.password.grant`, `authority.client_credentials.grant`) surface `audit.scopes` and, on denials, a `scope.invalid` metadata entry so operators can trace exception approval attempts without inspecting downstream services. + +### 2.3 Cross-tenant scenarios + +- Platform operators with `tenant:admin` can assume other tenants via `/authority/tenant/switch` if explicitly permitted. +- CLI commands accept `--tenant ` to override environment default; Authority logs tenant switch events (`authority.tenant.switch`). +- Console tenant picker uses delegated token exchange (`/token/exchange`) to obtain scoped tenant tokens without exposing raw credentials. + +--- + +## 3 · Configuration changes + +### 3.1 Authority configuration (`authority.yaml`) + +Add new scopes and optional claims transformations: + +```yaml +security: + scopes: + - name: advisory:ingest + description: Concelier raw ingestion (append-only) + - name: advisory:read + description: Read Concelier advisories and guard verdicts + - name: vex:ingest + description: Excititor raw ingestion + - name: vex:read + description: Read Excititor VEX records + - name: aoc:verify + description: Run AOC verification + - name: effective:write + description: Policy Engine materialisation + - name: findings:read + description: Read derived findings + - name: graph:write + description: Cartographer build submissions + - name: graph:read + description: Read graph overlays + - name: graph:export + description: Export graph artefacts + - name: graph:simulate + description: Run graph what-if simulations + - name: vuln:read + description: Read Vuln Explorer data + claimTransforms: + - match: { scope: "effective:write" } + require: + serviceIdentity: policy-engine + - match: { scope: "graph:write" } + require: + serviceIdentity: cartographer +``` + +### 3.2 Client registration + +Update service clients: + +- `Concelier.WebService` → request `advisory:ingest`, `advisory:read`. +- `Excititor.WebService` → request `vex:ingest`, `vex:read`. +- `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`. +- `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`. +- `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required. +- `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read` plus existing UI scopes. +- `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed. + +Client definition snippet: + +```yaml +clients: + - clientId: concelier-web + grantTypes: [client_credentials] + scopes: [advisory:ingest, advisory:read] + tenants: [default] + - clientId: policy-engine + grantTypes: [client_credentials] + scopes: [effective:write, findings:read] + properties: + serviceIdentity: policy-engine + - clientId: cartographer-service + grantTypes: [client_credentials] + scopes: [graph:write, graph:read] + properties: + serviceIdentity: cartographer +``` + +--- + +## 4 · Operational safeguards + +- **Audit events:** Authority emits `authority.scope.granted` and `authority.scope.revoked` events with `scope` and `tenant`. Monitor for unexpected grants. +- **Rate limiting:** Apply stricter limits on `/token` endpoints for clients requesting `advisory:ingest` or `vex:ingest` to mitigate brute-force ingestion attempts. +- **Incident response:** Link AOC alerts to Authority audit logs to confirm whether violations come from expected identities. +- **Rotation:** Rotate ingest client secrets alongside guard deployments; add rotation steps to `ops/authority-key-rotation.md`. +- **Testing:** Integration tests must fail if tokens lacking `tenant` attempt ingestion; add coverage in Concelier/Excititor smoke suites (see `CONCELIER-CORE-AOC-19-013`). + +--- + +## 5 · Offline & air-gap notes + +- Offline Kit bundles include tenant-scoped service credentials. Ensure ingest bundles ship without `advisory:ingest` scopes unless strictly required. +- CLI verification in offline environments uses pre-issued `aoc:verify` tokens; document expiration and renewal processes. +- Authority replicas in air-gapped environments should restrict scope issuance to known tenants and log all `/token` interactions for later replay. + +--- + +## 6 · References + +- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) +- [Architecture overview](../modules/platform/architecture-overview.md) +- [Concelier architecture](../modules/concelier/architecture.md) +- [Excititor architecture](../modules/excititor/architecture.md) +- [Policy governance](policy-governance.md) +- [Authority key rotation playbook](../ops/authority-key-rotation.md) + +--- + +## 7 · Compliance checklist + +- [ ] Scope catalogue updated in Authority configuration templates. +- [ ] Role mappings documented for each tenant profile. +- [ ] Claim transforms enforce `serviceIdentity` for `effective:write`. +- [ ] Claim transforms enforce `serviceIdentity` for `graph:write`. +- [ ] Concelier/Excititor smoke tests cover missing tenant rejection. +- [ ] Offline kit credentials reviewed for least privilege. +- [ ] Audit/monitoring guidance validated with Observability Guild. +- [ ] Authority Core sign-off recorded (owner: @authority-core, due 2025-10-28). + +--- + +*Last updated: 2025-10-27 (Sprint 19).* diff --git a/docs/ui/admin.md b/docs/ui/admin.md index 00fd03e4..47d80fb6 100644 --- a/docs/ui/admin.md +++ b/docs/ui/admin.md @@ -1,174 +1,174 @@ -# StellaOps Console - Admin Workspace - -> **Audience:** Authority Guild, Console admins, support engineers, tenant operators. -> **Scope:** Tenant management, role mapping, token lifecycle, integrations, fresh-auth prompts, security guardrails, offline behaviour, and compliance checklist for Sprint 23. - -The Admin workspace centralises Authority-facing controls: tenants, roles, API clients, tokens, and integrations. It surfaces RBAC mappings, token issuance logs, and bootstrap flows with the same offline-first guarantees as the rest of the console. - ---- - -## 1. Access and prerequisites - -- **Route:** `/console/admin` with sub-routes for tenants, users, roles, tokens, integrations, audit, and bootstrap. -- **Scopes:** - - `ui.admin` (base access) - - `authority:tenants.read` / `authority:tenants.write` - - `authority:roles.read` / `authority:roles.write` - - `authority:tokens.read` / `authority:tokens.revoke` - - `authority:clients.read` / `authority:clients.write` - - `authority:audit.read` (view audit trails) -- **Fresh-auth:** Sensitive actions (token revoke, bootstrap key issue, signing key rotation) require fresh-auth challenge. -- **Dependencies:** Authority service (`/internal/*` APIs), revocation export, JWKS, licensing posture endpoint, integration config store. - ---- - -## 2. Layout overview - -``` -+--------------------------------------------------------------------+ -| Header: Tenant picker - environment badge - security banner | -+--------------------------------------------------------------------+ -| Tabs: Tenants | Roles & Scopes | Users & Tokens | Integrations | Audit | -+--------------------------------------------------------------------+ -| Sidebar: Quick actions (Invite user, Create client, Export revocations) -| Main panel varies per tab | -+--------------------------------------------------------------------+ -``` - -The header includes offline status indicator and link to Authority health page. - ---- - -## 3. Tenants tab - -| Field | Description | -|-------|-------------| -| **Tenant ID** | Lowercase slug used in tokens and client registrations. | -| **Display name** | Human-friendly name. | -| **Status** | `active`, `suspended`, `pending`. Suspended tenants block token issuance. | -| **Isolation mode** | `dedicated`, `shared`, or `sandbox`. Drives RBAC defaults. | -| **Default roles** | Roles automatically assigned to new users within the tenant. | -| **Offline snapshots** | Latest snapshot timestamp, checksum, operator. | - -Actions: - -- `Create tenant` (requires `authority:tenants.write`). Form captures display name, slug, isolation mode, default roles, bootstrap contact, optional plan metadata. -- `Suspend/Resume` toggles token issuance and surfaces audit entry. -- `Export tenant bundle` downloads tenant-specific revocation + JWKS package for air-gap distribution. -- CLI parity: `stella auth tenant create --tenant `, `stella auth tenant suspend --tenant `. - ---- - -## 4. Roles & scopes tab - -- Table lists roles with mapped scopes and audiences. -- Inline editor supports adding/removing scopes (with validation). -- Scope categories: UI, Scanner, Concelier, Excititor, Policy, Attestor, Notifier, Scheduler, Offline kit. -- Visual diff shows impact of changes on linked clients/users before committing. -- "Effective permissions" view summarises what each role grants per service. -- CLI parity: `stella auth role update --role ui.admin --add-scope authority:tokens.revoke`. - ---- - -## 5. Users & tokens tab - -Sections: - -1. **User list** - identity, tenant, roles, last login, MFA status. Actions include reset password (if plugin supports), enforce fresh-auth, disable user. -2. **Token inventory** - lists active tokens (access/refresh/device). Columns: token ID, type, subject, audience, issued at, expires, status. Toggle to show revoked tokens. -3. **Token details** drawer shows claims, sender constraint (`cnf`), issuance metadata, revocation history. -4. **Revoke token** action requires fresh-auth and prompts for reason (incident, user request, compromise). -5. **Bulk revoke** (per tenant or role) triggers Authority revocation export to ensure downstream services purge caches. - -Audit entries appear for every user/token change. CLI parity: `stella auth token revoke --token `. - ---- - -## 6. Integrations tab - -- **Authority clients** list (service accounts) with grant types, allowed scopes, DPoP/mTLS settings, tenant hints, and rotation status. -- **Bootstrap bundles** - downloadable templates for new clients/users; includes configuration YAML and CLI instructions. -- **External IdP connectors** (optional) - displays status for SAML/OIDC plugins; includes metadata upload field and test login result. -- **Licensing posture** - read-only panel summarising plan tier, entitlement expiry, and contact info (pulled from licensing service). -- **Notifications** - optional webhook configuration for token events (on revoke, on failure). -- CLI parity: `stella auth client create --client concelier --grant client_credentials --tenant prod`. - ---- - -## 7. Audit tab - -- Timeline view of administrative events (user changes, role updates, token revocations, bootstrap actions, key rotations). -- Filters: event type, actor, tenant, scope, correlation ID. -- Export button downloads CSV/JSON for SOC ingestion. -- "Open in logs" copies search query pre-populated with correlation IDs. -- CLI parity: `stella auth audit export --from 2025-10-20`. - ---- - -## 8. Fresh-auth prompts - -- High-risk actions (revoke all tokens, rotate signing key, create privileged client) trigger modal requiring credential re-entry or hardware key touch. -- Fresh-auth window is 5 minutes; countdown displayed. -- UI surface indicates when current session is outside fresh-auth window; sensitive buttons disabled until re-auth. -- Audit log records fresh-auth events (`authority.fresh_auth.start`, `authority.fresh_auth.success`). -- CLI parity: `stella auth fresh-auth` obtains short-lived token for scriptable flows. - ---- - -## 9. Security guardrails - -- DPoP enforcement reminders for UI clients; console warns if any client lacks sender constraint. -- mTLS enforcement summary for high-value audiences (Signer/Attestor). -- Token policy checklists (access token TTL, refresh token policy) with alerts when deviating from defaults. -- Revocation bundle export status (timestamp, digest, operator). -- Key rotation panel showing current `kid`, last rotation, next scheduled rotation, and manual trigger button (ties into Authority rotate API). -- CLI parity: `stella auth signing rotate` for script automation. - ---- - -## 10. Offline and air-gap behaviour - -- Offline banner indicates snapshot version; disables direct remote calls. -- Tenant/role edits queue change manifests; UI instructs users to apply via CLI (`stella auth apply --bundle `). -- Token inventory shows snapshot state; revoke buttons generate scripts for offline Authority host. -- Integrations tab offers manual download/upload for client definitions and IdP metadata. -- Audit exports default to local storage with checksum output for transfer. - ---- - -## 11. Screenshot coordination - -- Placeholders: - - `![Admin tenants placeholder](../assets/ui/admin/tenants-placeholder.png)` - - `![Admin roles placeholder](../assets/ui/admin/roles-placeholder.png)` - - `![Admin tokens placeholder](../assets/ui/admin/tokens-placeholder.png)` -- Capture real screenshots with Authority Guild once Sprint 23 UI is final (tracked in `#console-screenshots`, 2025-10-26 entry). Provide both light and dark theme variants. - ---- - -## 12. References - -- `/docs/ARCHITECTURE_AUTHORITY.md` - Authority architecture. -- `/docs/11_AUTHORITY.md` - Authority service overview. -- `/docs/security/authority-scopes.md` - scope definitions. -- `/docs/ui/policies.md` - policy approvals requiring fresh-auth. -- `/docs/ui/console-overview.md` - navigation shell. -- `/docs/cli/authentication.md` (pending) and `/docs/cli/policy.md` for CLI flows. -- `/docs/ops/scheduler-runbook.md` for integration with scheduler token rotation. - ---- - -## 13. Compliance checklist - -- [ ] Tenants, roles/scopes, and token management documented with actions and CLI parity. -- [ ] Integrations and audit views covered. -- [ ] Fresh-auth prompts and guardrails described. -- [ ] Security controls (DPoP, mTLS, key rotation, revocations) captured. -- [ ] Offline behaviour explained with script guidance. -- [ ] Screenshot placeholders and coordination noted. -- [ ] References validated. - ---- - -*Last updated: 2025-10-26 (Sprint 23).* - +# StellaOps Console - Admin Workspace + +> **Audience:** Authority Guild, Console admins, support engineers, tenant operators. +> **Scope:** Tenant management, role mapping, token lifecycle, integrations, fresh-auth prompts, security guardrails, offline behaviour, and compliance checklist for Sprint 23. + +The Admin workspace centralises Authority-facing controls: tenants, roles, API clients, tokens, and integrations. It surfaces RBAC mappings, token issuance logs, and bootstrap flows with the same offline-first guarantees as the rest of the console. + +--- + +## 1. Access and prerequisites + +- **Route:** `/console/admin` with sub-routes for tenants, users, roles, tokens, integrations, audit, and bootstrap. +- **Scopes:** + - `ui.admin` (base access) + - `authority:tenants.read` / `authority:tenants.write` + - `authority:roles.read` / `authority:roles.write` + - `authority:tokens.read` / `authority:tokens.revoke` + - `authority:clients.read` / `authority:clients.write` + - `authority:audit.read` (view audit trails) +- **Fresh-auth:** Sensitive actions (token revoke, bootstrap key issue, signing key rotation) require fresh-auth challenge. +- **Dependencies:** Authority service (`/internal/*` APIs), revocation export, JWKS, licensing posture endpoint, integration config store. + +--- + +## 2. Layout overview + +``` ++--------------------------------------------------------------------+ +| Header: Tenant picker - environment badge - security banner | ++--------------------------------------------------------------------+ +| Tabs: Tenants | Roles & Scopes | Users & Tokens | Integrations | Audit | ++--------------------------------------------------------------------+ +| Sidebar: Quick actions (Invite user, Create client, Export revocations) +| Main panel varies per tab | ++--------------------------------------------------------------------+ +``` + +The header includes offline status indicator and link to Authority health page. + +--- + +## 3. Tenants tab + +| Field | Description | +|-------|-------------| +| **Tenant ID** | Lowercase slug used in tokens and client registrations. | +| **Display name** | Human-friendly name. | +| **Status** | `active`, `suspended`, `pending`. Suspended tenants block token issuance. | +| **Isolation mode** | `dedicated`, `shared`, or `sandbox`. Drives RBAC defaults. | +| **Default roles** | Roles automatically assigned to new users within the tenant. | +| **Offline snapshots** | Latest snapshot timestamp, checksum, operator. | + +Actions: + +- `Create tenant` (requires `authority:tenants.write`). Form captures display name, slug, isolation mode, default roles, bootstrap contact, optional plan metadata. +- `Suspend/Resume` toggles token issuance and surfaces audit entry. +- `Export tenant bundle` downloads tenant-specific revocation + JWKS package for air-gap distribution. +- CLI parity: `stella auth tenant create --tenant `, `stella auth tenant suspend --tenant `. + +--- + +## 4. Roles & scopes tab + +- Table lists roles with mapped scopes and audiences. +- Inline editor supports adding/removing scopes (with validation). +- Scope categories: UI, Scanner, Concelier, Excititor, Policy, Attestor, Notifier, Scheduler, Offline kit. +- Visual diff shows impact of changes on linked clients/users before committing. +- "Effective permissions" view summarises what each role grants per service. +- CLI parity: `stella auth role update --role ui.admin --add-scope authority:tokens.revoke`. + +--- + +## 5. Users & tokens tab + +Sections: + +1. **User list** - identity, tenant, roles, last login, MFA status. Actions include reset password (if plugin supports), enforce fresh-auth, disable user. +2. **Token inventory** - lists active tokens (access/refresh/device). Columns: token ID, type, subject, audience, issued at, expires, status. Toggle to show revoked tokens. +3. **Token details** drawer shows claims, sender constraint (`cnf`), issuance metadata, revocation history. +4. **Revoke token** action requires fresh-auth and prompts for reason (incident, user request, compromise). +5. **Bulk revoke** (per tenant or role) triggers Authority revocation export to ensure downstream services purge caches. + +Audit entries appear for every user/token change. CLI parity: `stella auth token revoke --token `. + +--- + +## 6. Integrations tab + +- **Authority clients** list (service accounts) with grant types, allowed scopes, DPoP/mTLS settings, tenant hints, and rotation status. +- **Bootstrap bundles** - downloadable templates for new clients/users; includes configuration YAML and CLI instructions. +- **External IdP connectors** (optional) - displays status for SAML/OIDC plugins; includes metadata upload field and test login result. +- **Licensing posture** - read-only panel summarising plan tier, entitlement expiry, and contact info (pulled from licensing service). +- **Notifications** - optional webhook configuration for token events (on revoke, on failure). +- CLI parity: `stella auth client create --client concelier --grant client_credentials --tenant prod`. + +--- + +## 7. Audit tab + +- Timeline view of administrative events (user changes, role updates, token revocations, bootstrap actions, key rotations). +- Filters: event type, actor, tenant, scope, correlation ID. +- Export button downloads CSV/JSON for SOC ingestion. +- "Open in logs" copies search query pre-populated with correlation IDs. +- CLI parity: `stella auth audit export --from 2025-10-20`. + +--- + +## 8. Fresh-auth prompts + +- High-risk actions (revoke all tokens, rotate signing key, create privileged client) trigger modal requiring credential re-entry or hardware key touch. +- Fresh-auth window is 5 minutes; countdown displayed. +- UI surface indicates when current session is outside fresh-auth window; sensitive buttons disabled until re-auth. +- Audit log records fresh-auth events (`authority.fresh_auth.start`, `authority.fresh_auth.success`). +- CLI parity: `stella auth fresh-auth` obtains short-lived token for scriptable flows. + +--- + +## 9. Security guardrails + +- DPoP enforcement reminders for UI clients; console warns if any client lacks sender constraint. +- mTLS enforcement summary for high-value audiences (Signer/Attestor). +- Token policy checklists (access token TTL, refresh token policy) with alerts when deviating from defaults. +- Revocation bundle export status (timestamp, digest, operator). +- Key rotation panel showing current `kid`, last rotation, next scheduled rotation, and manual trigger button (ties into Authority rotate API). +- CLI parity: `stella auth signing rotate` for script automation. + +--- + +## 10. Offline and air-gap behaviour + +- Offline banner indicates snapshot version; disables direct remote calls. +- Tenant/role edits queue change manifests; UI instructs users to apply via CLI (`stella auth apply --bundle `). +- Token inventory shows snapshot state; revoke buttons generate scripts for offline Authority host. +- Integrations tab offers manual download/upload for client definitions and IdP metadata. +- Audit exports default to local storage with checksum output for transfer. + +--- + +## 11. Screenshot coordination + +- Placeholders: + - `![Admin tenants placeholder](../assets/ui/admin/tenants-placeholder.png)` + - `![Admin roles placeholder](../assets/ui/admin/roles-placeholder.png)` + - `![Admin tokens placeholder](../assets/ui/admin/tokens-placeholder.png)` +- Capture real screenshots with Authority Guild once Sprint 23 UI is final (tracked in `#console-screenshots`, 2025-10-26 entry). Provide both light and dark theme variants. + +--- + +## 12. References + +- `/docs/modules/authority/architecture.md` - Authority architecture. +- `/docs/11_AUTHORITY.md` - Authority service overview. +- `/docs/security/authority-scopes.md` - scope definitions. +- `/docs/ui/policies.md` - policy approvals requiring fresh-auth. +- `/docs/ui/console-overview.md` - navigation shell. +- `/docs/modules/cli/guides/authentication.md` (pending) and `/docs/modules/cli/guides/policy.md` for CLI flows. +- `/docs/modules/scheduler/operations/worker.md` for integration with scheduler token rotation. + +--- + +## 13. Compliance checklist + +- [ ] Tenants, roles/scopes, and token management documented with actions and CLI parity. +- [ ] Integrations and audit views covered. +- [ ] Fresh-auth prompts and guardrails described. +- [ ] Security controls (DPoP, mTLS, key rotation, revocations) captured. +- [ ] Offline behaviour explained with script guidance. +- [ ] Screenshot placeholders and coordination noted. +- [ ] References validated. + +--- + +*Last updated: 2025-10-26 (Sprint 23).* + diff --git a/docs/ui/console.md b/docs/ui/console.md index c6c9f905..08f65cb9 100644 --- a/docs/ui/console.md +++ b/docs/ui/console.md @@ -1,144 +1,144 @@ -# Console AOC Dashboard - -> **Audience:** Console PMs, UI engineers, Concelier/Excititor operators, SREs monitoring ingestion health. -> **Scope:** Layout, RBAC, workflow, and observability for the Aggregation-Only Contract (AOC) dashboard that ships with Sprint 19. - -The Console AOC dashboard gives operators a live view of ingestion guardrails across all configured sources. It surfaces raw Concelier/Excititor health, highlights violations raised by `AOCWriteGuard`, and lets on-call staff trigger verification without leaving the browser. Use it alongside the [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) and the [architecture overview](../architecture/overview.md) when rolling out AOC changes. - ---- - -## 1 · Access & prerequisites - -- **Route:** `/console/sources` (dashboard) with contextual drawer routes `/console/sources/:sourceKey` and `/console/sources/:sourceKey/violations/:documentId`. -- **Feature flag:** `aocDashboard.enabled` (default `true` once Concelier WebService exposes `/aoc/verify`). Toggle is tenant-scoped to support phased rollout. -- **Scopes:** - - `ui.read` (base navigation) plus `advisory:read` to view Concelier ingestion metrics/violations. - - `vex:read` to see Excititor entries and run VEX verifications. - - `aoc:verify` to trigger guard runs from the dashboard action bar. - - `advisory:ingest` / `vex:ingest` **not** required; the dashboard uses read-only APIs. -- **Tenancy:** All data is filtered by the active tenant selector. Switching tenants re-fetches tiles and drill-down tables with tenant-scoped tokens. -- **Back-end contracts:** Requires Concelier/Excititor 19.x (AOC guards enabled) and Authority scopes updated per [Authority service docs](../ARCHITECTURE_AUTHORITY.md#new-aoc-scopes). - ---- - -## 2 · Layout overview - -``` -┌────────────────────────────────────────────────────────────────────────────┐ -│ Header: tenant picker • live status pill • Last verify (“2h ago”) │ -├────────────────────────────────────────────────────────────────────────────┤ -│ Tile grid (4 per row) │ -│ ┌───── Concelier sources ─────┐ ┌────── Excititor sources ────────┐ │ -│ │ Red Hat | Ubuntu | OSV ... │ │ Vendor VEX | CSAF feeds ... │ │ -├────────────────────────────────────────────────────────────────────────────┤ -│ Violations & history table │ -│ • Filters: timeframe, source, ERR_AOC code, severity (warning/block) │ -│ • Columns: timestamp, source, code, summary, supersedes link, actions │ -├────────────────────────────────────────────────────────────────────────────┤ -│ Action bar: Run Verify • Download CSV • Open Concelier raw doc • Help │ -└────────────────────────────────────────────────────────────────────────────┘ -``` - -Tiles summarise the latest ingestion runs. The table and drawers provide drill-down views, and the action bar launches verifier workflows or exports evidence for audits. - ---- - -## 3 · Source tiles - -Each tile represents a Concelier or Excititor source and contains the fields below. - -| Field | Description | Thresholds & colours | -| ------ | ----------- | -------------------- | -| **Status badge** | Aggregated health computed from the latest job. | `Healthy` (green) when last job finished < 30 min ago and `violations24h = 0`; `Warning` (amber) when age ≥ 30 min or ≤ 5 violations; `Critical` (red) on any guard rejection (`ERR_AOC_00x`) or if job age > 2 h. | -| **Last ingest** | Timestamp and relative age of last successful append to `advisory_raw`/`vex_raw`. | Clicking opens job detail drawer. | -| **Violations (24 h)** | Count of guard failures grouped by `ERR_AOC` code across the last 24 hours. | Shows pill per code (e.g., `ERR_AOC_001 × 2`). | -| **Supersedes depth** | Average length of supersedes chain for the source over the last day. | Helps spot runaway revisions. | -| **Signature pass rate** | % of documents where signature/checksum verification succeeded. | Derived from `ingestion_signature_verified_total`. | -| **Latency P95** | Write latency recorded by ingestion spans / histograms. | Mirrors `ingestion_latency_seconds{quantile=0.95}`. | - -Tile menus expose quick actions: - -- **View history** – jumps to table filtered by the selected source. -- **Open metrics** – deep links to Grafana panel seeded with `source=` for `ingestion_write_total` and `aoc_violation_total`. -- **Download raw sample** – fetches the most recent document via `GET /advisories/raw/{id}` (or VEX equivalent) for debugging. - ---- - -## 4 · Violation drill-down workflow - -1. **Select a tile** or use table filters to focus on a source, timeframe, or `ERR_AOC` code. -2. **Inspect the violation row:** summary shows offending field, guard code, and document hash. -3. **Open detail drawer:** reveals provenance (source URI, signature info), supersedes chain, and raw JSON (redacted secrets). Drawer also lists linked `effective_finding_*` entries if Policy Engine has already materialised overlays. -4. **Remediate / annotate:** operators can add notes (stored as structured annotations) or flag as *acknowledged* (for on-call rotations). Annotations sync to Concelier audit logs. -5. **Escalate:** “Create incident” button opens the standard incident template pre-filled with context (requires `ui.incidents` scope). - -The drill-down retains filter state, so back navigation returns to the scoped table without reloading the entire dashboard. - ---- - -## 5 · Verification & actions - -- **Run Verify:** calls `POST /aoc/verify` with the chosen `since` window (default 24 h). UI displays summary cards (documents checked, violations found, top codes) and stores reports for 7 days. Results include a downloadable JSON manifest mirroring CLI output. -- **Schedule verify:** schedule modal configures automated verification (daily/weekly) and optional email/Notifier hooks. -- **Export evidence:** CSV/JSON export buttons include tile metrics, verification summaries, and violation annotations—useful for audits. -- **Open in CLI:** copies `stella aoc verify --tenant --since ` for parity with automation scripts. - -All verify actions are scoped by tenant and recorded in Authority audit logs (`action=aoc.verify.ui`). - ---- - -## 6 · Metrics & observability - -The dashboard consumes the same metrics emitted by Concelier/Excititor (documented in the [AOC reference](../ingestion/aggregation-only-contract.md#9-observability-and-diagnostics)): - -- `ingestion_write_total{source,tenant,result}` – populates success/error sparklines beneath each tile. -- `aoc_violation_total{source,tenant,code}` – feeds violation pills and trend chart. -- `ingestion_signature_verified_total{source,result}` – renders signature pass-rate gauge. -- `ingestion_latency_seconds{source,quantile}` – used for latency badges and alert banners. -- `advisory_revision_count{source}` – displayed in supersedes depth tooltip. - -The page shows the correlation ID for each violation entry, matching structured logs emitted by Concelier and Excititor, enabling quick log pivoting. - ---- - -## 7 · Security & tenancy - -- Tokens are DPoP-bound; every API call includes the UI’s DPoP proof and inherits tenant scoping from Authority. -- Violations drawer hides sensitive fields (credentials, private keys) using the same redaction rules as Concelier events. -- Run Verify honours rate limits to avoid overloading ingestion services; repeated failures trigger a cool-down banner. -- The dashboard never exposes derived severity or policy status—only raw ingestion facts and guard results, preserving AOC separation of duties. - ---- - -## 8 · Offline & air-gap behaviour - -- In sealed/offline mode the dashboard switches to **“offline snapshot”** banner, reading from Offline Kit snapshots seeded via `ouk` imports. -- Verification requests queue until connectivity resumes; UI provides `Download script` to run `stella aoc verify` on a workstation and upload results later. -- Tiles display the timestamp of the last imported snapshot and flag when it exceeds the configured staleness threshold (default 48 h offline). -- CSV/JSON exports include checksums so operators can transfer evidence across air gaps securely. - ---- - -## 9 · Related references - -- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) -- [Architecture overview](../architecture/overview.md) -- [Concelier architecture](../ARCHITECTURE_CONCELIER.md) -- [Excititor architecture](../ARCHITECTURE_EXCITITOR.md) -- [CLI AOC commands](../cli/cli-reference.md) - ---- - -## 10 · Compliance checklist - -- [ ] Dashboard wired to live AOC metrics (`ingestion_*`, `aoc_violation_total`). -- [ ] Verify action logs to Authority audit trail with tenant context. -- [ ] UI enforces read-only access to raw stores; no mutation endpoints invoked. -- [ ] Offline/air-gap mode documented and validated with Offline Kit snapshots. -- [ ] Violation exports include provenance and `ERR_AOC_00x` codes. -- [ ] Accessibility tested (WCAG 2.2 AA) for tiles, tables, and drawers. -- [ ] Screenshot/recording captured for Docs release notes (pending UI capture). - ---- - -*Last updated: 2025-10-26 (Sprint 19).* +# Console AOC Dashboard + +> **Audience:** Console PMs, UI engineers, Concelier/Excititor operators, SREs monitoring ingestion health. +> **Scope:** Layout, RBAC, workflow, and observability for the Aggregation-Only Contract (AOC) dashboard that ships with Sprint 19. + +The Console AOC dashboard gives operators a live view of ingestion guardrails across all configured sources. It surfaces raw Concelier/Excititor health, highlights violations raised by `AOCWriteGuard`, and lets on-call staff trigger verification without leaving the browser. Use it alongside the [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) and the [architecture overview](../modules/platform/architecture-overview.md) when rolling out AOC changes. + +--- + +## 1 · Access & prerequisites + +- **Route:** `/console/sources` (dashboard) with contextual drawer routes `/console/sources/:sourceKey` and `/console/sources/:sourceKey/violations/:documentId`. +- **Feature flag:** `aocDashboard.enabled` (default `true` once Concelier WebService exposes `/aoc/verify`). Toggle is tenant-scoped to support phased rollout. +- **Scopes:** + - `ui.read` (base navigation) plus `advisory:read` to view Concelier ingestion metrics/violations. + - `vex:read` to see Excititor entries and run VEX verifications. + - `aoc:verify` to trigger guard runs from the dashboard action bar. + - `advisory:ingest` / `vex:ingest` **not** required; the dashboard uses read-only APIs. +- **Tenancy:** All data is filtered by the active tenant selector. Switching tenants re-fetches tiles and drill-down tables with tenant-scoped tokens. +- **Back-end contracts:** Requires Concelier/Excititor 19.x (AOC guards enabled) and Authority scopes updated per [Authority service docs](../modules/authority/architecture.md#new-aoc-scopes). + +--- + +## 2 · Layout overview + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ Header: tenant picker • live status pill • Last verify (“2h ago”) │ +├────────────────────────────────────────────────────────────────────────────┤ +│ Tile grid (4 per row) │ +│ ┌───── Concelier sources ─────┐ ┌────── Excititor sources ────────┐ │ +│ │ Red Hat | Ubuntu | OSV ... │ │ Vendor VEX | CSAF feeds ... │ │ +├────────────────────────────────────────────────────────────────────────────┤ +│ Violations & history table │ +│ • Filters: timeframe, source, ERR_AOC code, severity (warning/block) │ +│ • Columns: timestamp, source, code, summary, supersedes link, actions │ +├────────────────────────────────────────────────────────────────────────────┤ +│ Action bar: Run Verify • Download CSV • Open Concelier raw doc • Help │ +└────────────────────────────────────────────────────────────────────────────┘ +``` + +Tiles summarise the latest ingestion runs. The table and drawers provide drill-down views, and the action bar launches verifier workflows or exports evidence for audits. + +--- + +## 3 · Source tiles + +Each tile represents a Concelier or Excititor source and contains the fields below. + +| Field | Description | Thresholds & colours | +| ------ | ----------- | -------------------- | +| **Status badge** | Aggregated health computed from the latest job. | `Healthy` (green) when last job finished < 30 min ago and `violations24h = 0`; `Warning` (amber) when age ≥ 30 min or ≤ 5 violations; `Critical` (red) on any guard rejection (`ERR_AOC_00x`) or if job age > 2 h. | +| **Last ingest** | Timestamp and relative age of last successful append to `advisory_raw`/`vex_raw`. | Clicking opens job detail drawer. | +| **Violations (24 h)** | Count of guard failures grouped by `ERR_AOC` code across the last 24 hours. | Shows pill per code (e.g., `ERR_AOC_001 × 2`). | +| **Supersedes depth** | Average length of supersedes chain for the source over the last day. | Helps spot runaway revisions. | +| **Signature pass rate** | % of documents where signature/checksum verification succeeded. | Derived from `ingestion_signature_verified_total`. | +| **Latency P95** | Write latency recorded by ingestion spans / histograms. | Mirrors `ingestion_latency_seconds{quantile=0.95}`. | + +Tile menus expose quick actions: + +- **View history** – jumps to table filtered by the selected source. +- **Open metrics** – deep links to Grafana panel seeded with `source=` for `ingestion_write_total` and `aoc_violation_total`. +- **Download raw sample** – fetches the most recent document via `GET /advisories/raw/{id}` (or VEX equivalent) for debugging. + +--- + +## 4 · Violation drill-down workflow + +1. **Select a tile** or use table filters to focus on a source, timeframe, or `ERR_AOC` code. +2. **Inspect the violation row:** summary shows offending field, guard code, and document hash. +3. **Open detail drawer:** reveals provenance (source URI, signature info), supersedes chain, and raw JSON (redacted secrets). Drawer also lists linked `effective_finding_*` entries if Policy Engine has already materialised overlays. +4. **Remediate / annotate:** operators can add notes (stored as structured annotations) or flag as *acknowledged* (for on-call rotations). Annotations sync to Concelier audit logs. +5. **Escalate:** “Create incident” button opens the standard incident template pre-filled with context (requires `ui.incidents` scope). + +The drill-down retains filter state, so back navigation returns to the scoped table without reloading the entire dashboard. + +--- + +## 5 · Verification & actions + +- **Run Verify:** calls `POST /aoc/verify` with the chosen `since` window (default 24 h). UI displays summary cards (documents checked, violations found, top codes) and stores reports for 7 days. Results include a downloadable JSON manifest mirroring CLI output. +- **Schedule verify:** schedule modal configures automated verification (daily/weekly) and optional email/Notifier hooks. +- **Export evidence:** CSV/JSON export buttons include tile metrics, verification summaries, and violation annotations—useful for audits. +- **Open in CLI:** copies `stella aoc verify --tenant --since ` for parity with automation scripts. + +All verify actions are scoped by tenant and recorded in Authority audit logs (`action=aoc.verify.ui`). + +--- + +## 6 · Metrics & observability + +The dashboard consumes the same metrics emitted by Concelier/Excititor (documented in the [AOC reference](../ingestion/aggregation-only-contract.md#9-observability-and-diagnostics)): + +- `ingestion_write_total{source,tenant,result}` – populates success/error sparklines beneath each tile. +- `aoc_violation_total{source,tenant,code}` – feeds violation pills and trend chart. +- `ingestion_signature_verified_total{source,result}` – renders signature pass-rate gauge. +- `ingestion_latency_seconds{source,quantile}` – used for latency badges and alert banners. +- `advisory_revision_count{source}` – displayed in supersedes depth tooltip. + +The page shows the correlation ID for each violation entry, matching structured logs emitted by Concelier and Excititor, enabling quick log pivoting. + +--- + +## 7 · Security & tenancy + +- Tokens are DPoP-bound; every API call includes the UI’s DPoP proof and inherits tenant scoping from Authority. +- Violations drawer hides sensitive fields (credentials, private keys) using the same redaction rules as Concelier events. +- Run Verify honours rate limits to avoid overloading ingestion services; repeated failures trigger a cool-down banner. +- The dashboard never exposes derived severity or policy status—only raw ingestion facts and guard results, preserving AOC separation of duties. + +--- + +## 8 · Offline & air-gap behaviour + +- In sealed/offline mode the dashboard switches to **“offline snapshot”** banner, reading from Offline Kit snapshots seeded via `ouk` imports. +- Verification requests queue until connectivity resumes; UI provides `Download script` to run `stella aoc verify` on a workstation and upload results later. +- Tiles display the timestamp of the last imported snapshot and flag when it exceeds the configured staleness threshold (default 48 h offline). +- CSV/JSON exports include checksums so operators can transfer evidence across air gaps securely. + +--- + +## 9 · Related references + +- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md) +- [Architecture overview](../modules/platform/architecture-overview.md) +- [Concelier architecture](../modules/concelier/architecture.md) +- [Excititor architecture](../modules/excititor/architecture.md) +- [CLI AOC commands](../modules/cli/guides/cli-reference.md) + +--- + +## 10 · Compliance checklist + +- [ ] Dashboard wired to live AOC metrics (`ingestion_*`, `aoc_violation_total`). +- [ ] Verify action logs to Authority audit trail with tenant context. +- [ ] UI enforces read-only access to raw stores; no mutation endpoints invoked. +- [ ] Offline/air-gap mode documented and validated with Offline Kit snapshots. +- [ ] Violation exports include provenance and `ERR_AOC_00x` codes. +- [ ] Accessibility tested (WCAG 2.2 AA) for tiles, tables, and drawers. +- [ ] Screenshot/recording captured for Docs release notes (pending UI capture). + +--- + +*Last updated: 2025-10-26 (Sprint 19).* diff --git a/docs/ui/findings.md b/docs/ui/findings.md index 2812ae7e..5dd6c22d 100644 --- a/docs/ui/findings.md +++ b/docs/ui/findings.md @@ -1,179 +1,179 @@ -# StellaOps Console - Findings - -> **Audience:** Policy Guild, Console UX team, security analysts, customer enablement. -> **Scope:** Findings list UX, filters, saved views, explain drawer, exports, CLI parity, real-time updates, and offline considerations for Sprint 23. - -The Findings workspace visualises materialised policy verdicts produced by the Policy Engine. It lets analysts triage affected components, inspect explain traces, compare policy views, and export evidence while respecting Aggregation-Only guardrails. - ---- - -## 1. Access and prerequisites - -- **Route:** `/console/findings` with optional panel parameters (e.g., `/console/findings?panel=explain&finding=`). -- **Scopes:** `findings.read` (list), `policy:runs` (view run metadata), `policy:simulate` (stage simulations), `downloads.read` (export bundles). -- **Prerequisites:** Policy Engine v2 (`policy_run` and `effective_finding_*` endpoints), Concelier/Excititor feeds for provenance, SBOM Service for component metadata. -- **Feature flags:** `findings.explain.enabled`, `findings.savedViews.enabled`, `findings.simulationDiff.enabled`. -- **Tenancy:** All queries include tenant context; cross-tenant comparisons require explicit admin scope and render split-pane view. - ---- - -## 2. Layout overview - -``` -+-------------------------------------------------------------------+ -| Header: Tenant badge - policy selector - global filters - actions | -+-------------------------------------------------------------------+ -| Top row cards: Affected assets - Critical count - KEV count | -+-------------------------------------------------------------------+ -| Findings grid (virtualised) | -| Columns: Status | Severity | Component | Policy | Source | Age | -| Row badges: KEV, Quieted, Override, Simulation only | -+-------------------------------------------------------------------+ -| Right drawer / full view tabs: Summary | Explain | Evidence | Run | -+-------------------------------------------------------------------+ -``` - -The policy selector includes Active, Staged, and Simulation snapshots. Switching snapshots triggers diff banners to highlight changes. - ---- - -## 3. Filters and saved views - -| Filter | Description | Notes | -|--------|-------------|-------| -| **Status** | `affected`, `at_risk`, `quieted`, `fixed`, `not_applicable`, `mitigated`. | Status definitions align with Policy Engine taxonomy. | -| **Severity** | Critical, High, Medium, Low, Informational, Untriaged. | Derived from policy scoring; UI displays numeric score tooltip. | -| **KEV** | Toggle to show only Known Exploited Vulnerabilities. | Pulls from Concelier enrichment. | -| **Policy** | Active, Staged, Simulation snapshots. | Simulation requires recent run; otherwise greyed out. | -| **Component** | PURL or substring search. | Autocomplete draws from current tenant findings. | -| **SBOM** | Filter by image digest or SBOM ID. | Includes quick links to SBOM Explorer. | -| **Tag** | Team or environment tags emitted by Policy Engine (`tags[]`). | Supports multi-select. | -| **Run window** | `Last 24h`, `Last 7d`, `Custom range`. | Applies to run timestamp. | -| **Explain hints** | Filter by explain artefact (rule ID, justification, VEX provider). | Uses server-side filter parameters. | - -Saved views persist filter combinations per tenant and policy. Users can mark views as shared; shared views appear in the left rail with owner and last updated timestamp. Keyboard shortcuts align with global presets (`Cmd+1-9 / Ctrl+1-9`). - ---- - -## 4. Findings grid - -| Column | Details | -|--------|---------| -| **Status** | Badge with tooltip describing resolution path (e.g., "Affected - blocked by policy rule R-105"). Quieted findings show a muted badge with expiry. | -| **Severity** | Numeric score and label. Hover reveals scoring formula and evidence sources. | -| **Component** | PURL plus human-friendly name. Includes SBOM badge linking to SBOM Explorer detail. | -| **Policy** | Policy name + revision digest; clicking opens policy diff in new tab. | -| **Source signals** | Icons for VEX, Advisory, Runtime overlays. Hover shows counts and last updated timestamps. | -| **Age** | Time since finding was last evaluated; colour-coded when exceeding SLA. | - -Row indicators: - -- **KEV** badge when Concelier marks the vulnerability as exploited. -- **Override** badge when policy override or exemption applied. -- **Simulation only** badge when viewing simulation snapshot; warns that finding is not yet active. -- **Determinism alert** icon if latest run reported a determinism mismatch (links to run detail). - -Bulk actions (multi-select): - -- `Open explains` (launch explain drawer for up to 10 findings). -- `Export CSV/JSON`. -- `Copy CLI` commands for batch explains (`stella findings explain --batch file`). -- `Create ticket` (integrates with integrations configured under Admin). - ---- - -## 5. Explain drawer - -Tabs inside the explain drawer: - -1. **Summary** - status, severity, policy decision, rule ID, last evaluated timestamp, SBOM link, run ID. -2. **Rule chain** - ordered list of policy rules triggered; each entry shows rule ID, name, action (block/warn/quiet), score contribution, and condition snippet. -3. **Evidence** - references to Concelier advisories, Excititor consensus, runtime signals, and overrides. Evidence entries link to their respective explorers. -4. **VEX impact** - table of VEX claims considered; displays provider, status, justification, acceptance (accepted/ignored), weight. -5. **History** - timeline of state transitions (affected -> quieted -> mitigated) with timestamps and operators (if override applied). -6. **Raw trace** - canonical JSON trace from Policy Engine (read-only). CLI parity snippet: - - `stella findings explain --policy --finding --format json`. - -Explain drawer includes copy-to-clipboard buttons for rule chain and evidence JSON to support audit workflows. When sealed mode is active, a banner highlights which evidence was sourced from cached data. - ---- - -## 6. Simulations and comparisons - -- Simulation toggle lets analysts compare Active vs Staged/Sandbox policies. -- Diff banner summarises added, removed, and changed findings. -- Side-by-side view shows baseline vs simulation verdicts with change badges (`added`, `removed`, `severity up`, `severity down`). -- CLI parity callout: `stella policy simulate --policy --sbom --format diff`. -- Simulation results persist for 7 days; stale simulations prompt re-run recommendation. - ---- - -## 7. Exports and automation - -- Immediate exports: CSV, JSON, Markdown summary for selected findings. -- Scheduled exports: asynchronous job to generate full tenant report (JSON + CSV) with manifest digests. -- Explain bundle export packages traces for a set of findings; includes manifest and hash for offline review. -- CLI parity: - - `stella findings ls --policy --format json --output findings.json` - - `stella findings export --policy --format csv --output findings.csv` - - `stella findings explain --batch batch.txt --output explains/` -- Automation: webhook copy button for `/downloads/hooks/subscribe?topic=findings.report.ready`. - ---- - -## 8. Real-time updates and observability - -- SSE channel `/console/findings/stream` pushes new findings, status changes, and quieted expirations; UI animates affected rows. -- Header cards show metrics: `findings_critical_total`, `findings_quieted_total`, `findings_kev_total`. -- Run ticker lists latest policy runs with status, duration, determinism hash. -- Error banners include correlation IDs linking to Policy Engine run logs. -- Metrics drill-down links to dashboards (OpenTelemetry, Prometheus). - ---- - -## 9. Offline and air-gap behaviour - -- Offline banner indicates snapshot ID and timestamp used for findings. -- Explain drawer notes when evidence references offline bundles; suggests importing updated advisories/VEX to refresh results. -- Exports default to local storage paths; UI provides manual transfer instructions. -- CLI examples switch to include `--sealed` or `--offline` flags. -- Tenant selector hides tenants without corresponding offline findings data to avoid partial views. - ---- - -## 10. Screenshot coordination - -- Placeholders: - - `![Findings grid placeholder](../assets/ui/findings/grid-placeholder.png)` - - `![Explain drawer placeholder](../assets/ui/findings/explain-placeholder.png)` -- Coordinate with Console Guild (Slack `#console-screenshots`, entry 2025-10-26) to capture updated light and dark theme shots before release. - ---- - -## 11. References - -- `/docs/ui/console-overview.md` - shell, filters, tenant model. -- `/docs/ui/navigation.md` - route list, deep-link schema. -- `/docs/ui/advisories-and-vex.md` - advisory and VEX context feeding findings. -- `/docs/ui/policies.md` (pending) - editor and policy lifecycle. -- `/docs/policy/overview.md` - Policy Engine outputs. -- `/docs/policy/runs.md` - run orchestration. -- `/docs/cli/policy.md` - CLI parity for findings commands. - ---- - -## 12. Compliance checklist - -- [ ] Filters and saved view behaviour documented with CLI alignment. -- [ ] Findings grid columns, badges, and bulk actions captured. -- [ ] Explain drawer walkthrough includes rule chain, evidence, and raw trace. -- [ ] Simulation diff behaviour and CLI callouts described. -- [ ] Exports (immediate and scheduled) plus webhook integration covered. -- [ ] Real-time updates, metrics, and error correlation documented. -- [ ] Offline behaviour and screenshot coordination noted. -- [ ] References validated. - ---- - -*Last updated: 2025-10-26 (Sprint 23).* - +# StellaOps Console - Findings + +> **Audience:** Policy Guild, Console UX team, security analysts, customer enablement. +> **Scope:** Findings list UX, filters, saved views, explain drawer, exports, CLI parity, real-time updates, and offline considerations for Sprint 23. + +The Findings workspace visualises materialised policy verdicts produced by the Policy Engine. It lets analysts triage affected components, inspect explain traces, compare policy views, and export evidence while respecting Aggregation-Only guardrails. + +--- + +## 1. Access and prerequisites + +- **Route:** `/console/findings` with optional panel parameters (e.g., `/console/findings?panel=explain&finding=`). +- **Scopes:** `findings.read` (list), `policy:runs` (view run metadata), `policy:simulate` (stage simulations), `downloads.read` (export bundles). +- **Prerequisites:** Policy Engine v2 (`policy_run` and `effective_finding_*` endpoints), Concelier/Excititor feeds for provenance, SBOM Service for component metadata. +- **Feature flags:** `findings.explain.enabled`, `findings.savedViews.enabled`, `findings.simulationDiff.enabled`. +- **Tenancy:** All queries include tenant context; cross-tenant comparisons require explicit admin scope and render split-pane view. + +--- + +## 2. Layout overview + +``` ++-------------------------------------------------------------------+ +| Header: Tenant badge - policy selector - global filters - actions | ++-------------------------------------------------------------------+ +| Top row cards: Affected assets - Critical count - KEV count | ++-------------------------------------------------------------------+ +| Findings grid (virtualised) | +| Columns: Status | Severity | Component | Policy | Source | Age | +| Row badges: KEV, Quieted, Override, Simulation only | ++-------------------------------------------------------------------+ +| Right drawer / full view tabs: Summary | Explain | Evidence | Run | ++-------------------------------------------------------------------+ +``` + +The policy selector includes Active, Staged, and Simulation snapshots. Switching snapshots triggers diff banners to highlight changes. + +--- + +## 3. Filters and saved views + +| Filter | Description | Notes | +|--------|-------------|-------| +| **Status** | `affected`, `at_risk`, `quieted`, `fixed`, `not_applicable`, `mitigated`. | Status definitions align with Policy Engine taxonomy. | +| **Severity** | Critical, High, Medium, Low, Informational, Untriaged. | Derived from policy scoring; UI displays numeric score tooltip. | +| **KEV** | Toggle to show only Known Exploited Vulnerabilities. | Pulls from Concelier enrichment. | +| **Policy** | Active, Staged, Simulation snapshots. | Simulation requires recent run; otherwise greyed out. | +| **Component** | PURL or substring search. | Autocomplete draws from current tenant findings. | +| **SBOM** | Filter by image digest or SBOM ID. | Includes quick links to SBOM Explorer. | +| **Tag** | Team or environment tags emitted by Policy Engine (`tags[]`). | Supports multi-select. | +| **Run window** | `Last 24h`, `Last 7d`, `Custom range`. | Applies to run timestamp. | +| **Explain hints** | Filter by explain artefact (rule ID, justification, VEX provider). | Uses server-side filter parameters. | + +Saved views persist filter combinations per tenant and policy. Users can mark views as shared; shared views appear in the left rail with owner and last updated timestamp. Keyboard shortcuts align with global presets (`Cmd+1-9 / Ctrl+1-9`). + +--- + +## 4. Findings grid + +| Column | Details | +|--------|---------| +| **Status** | Badge with tooltip describing resolution path (e.g., "Affected - blocked by policy rule R-105"). Quieted findings show a muted badge with expiry. | +| **Severity** | Numeric score and label. Hover reveals scoring formula and evidence sources. | +| **Component** | PURL plus human-friendly name. Includes SBOM badge linking to SBOM Explorer detail. | +| **Policy** | Policy name + revision digest; clicking opens policy diff in new tab. | +| **Source signals** | Icons for VEX, Advisory, Runtime overlays. Hover shows counts and last updated timestamps. | +| **Age** | Time since finding was last evaluated; colour-coded when exceeding SLA. | + +Row indicators: + +- **KEV** badge when Concelier marks the vulnerability as exploited. +- **Override** badge when policy override or exemption applied. +- **Simulation only** badge when viewing simulation snapshot; warns that finding is not yet active. +- **Determinism alert** icon if latest run reported a determinism mismatch (links to run detail). + +Bulk actions (multi-select): + +- `Open explains` (launch explain drawer for up to 10 findings). +- `Export CSV/JSON`. +- `Copy CLI` commands for batch explains (`stella findings explain --batch file`). +- `Create ticket` (integrates with integrations configured under Admin). + +--- + +## 5. Explain drawer + +Tabs inside the explain drawer: + +1. **Summary** - status, severity, policy decision, rule ID, last evaluated timestamp, SBOM link, run ID. +2. **Rule chain** - ordered list of policy rules triggered; each entry shows rule ID, name, action (block/warn/quiet), score contribution, and condition snippet. +3. **Evidence** - references to Concelier advisories, Excititor consensus, runtime signals, and overrides. Evidence entries link to their respective explorers. +4. **VEX impact** - table of VEX claims considered; displays provider, status, justification, acceptance (accepted/ignored), weight. +5. **History** - timeline of state transitions (affected -> quieted -> mitigated) with timestamps and operators (if override applied). +6. **Raw trace** - canonical JSON trace from Policy Engine (read-only). CLI parity snippet: + - `stella findings explain --policy --finding --format json`. + +Explain drawer includes copy-to-clipboard buttons for rule chain and evidence JSON to support audit workflows. When sealed mode is active, a banner highlights which evidence was sourced from cached data. + +--- + +## 6. Simulations and comparisons + +- Simulation toggle lets analysts compare Active vs Staged/Sandbox policies. +- Diff banner summarises added, removed, and changed findings. +- Side-by-side view shows baseline vs simulation verdicts with change badges (`added`, `removed`, `severity up`, `severity down`). +- CLI parity callout: `stella policy simulate --policy --sbom --format diff`. +- Simulation results persist for 7 days; stale simulations prompt re-run recommendation. + +--- + +## 7. Exports and automation + +- Immediate exports: CSV, JSON, Markdown summary for selected findings. +- Scheduled exports: asynchronous job to generate full tenant report (JSON + CSV) with manifest digests. +- Explain bundle export packages traces for a set of findings; includes manifest and hash for offline review. +- CLI parity: + - `stella findings ls --policy --format json --output findings.json` + - `stella findings export --policy --format csv --output findings.csv` + - `stella findings explain --batch batch.txt --output explains/` +- Automation: webhook copy button for `/downloads/hooks/subscribe?topic=findings.report.ready`. + +--- + +## 8. Real-time updates and observability + +- SSE channel `/console/findings/stream` pushes new findings, status changes, and quieted expirations; UI animates affected rows. +- Header cards show metrics: `findings_critical_total`, `findings_quieted_total`, `findings_kev_total`. +- Run ticker lists latest policy runs with status, duration, determinism hash. +- Error banners include correlation IDs linking to Policy Engine run logs. +- Metrics drill-down links to dashboards (OpenTelemetry, Prometheus). + +--- + +## 9. Offline and air-gap behaviour + +- Offline banner indicates snapshot ID and timestamp used for findings. +- Explain drawer notes when evidence references offline bundles; suggests importing updated advisories/VEX to refresh results. +- Exports default to local storage paths; UI provides manual transfer instructions. +- CLI examples switch to include `--sealed` or `--offline` flags. +- Tenant selector hides tenants without corresponding offline findings data to avoid partial views. + +--- + +## 10. Screenshot coordination + +- Placeholders: + - `![Findings grid placeholder](../assets/ui/findings/grid-placeholder.png)` + - `![Explain drawer placeholder](../assets/ui/findings/explain-placeholder.png)` +- Coordinate with Console Guild (Slack `#console-screenshots`, entry 2025-10-26) to capture updated light and dark theme shots before release. + +--- + +## 11. References + +- `/docs/ui/console-overview.md` - shell, filters, tenant model. +- `/docs/ui/navigation.md` - route list, deep-link schema. +- `/docs/ui/advisories-and-vex.md` - advisory and VEX context feeding findings. +- `/docs/ui/policies.md` (pending) - editor and policy lifecycle. +- `/docs/policy/overview.md` - Policy Engine outputs. +- `/docs/policy/runs.md` - run orchestration. +- `/docs/modules/cli/guides/policy.md` - CLI parity for findings commands. + +--- + +## 12. Compliance checklist + +- [ ] Filters and saved view behaviour documented with CLI alignment. +- [ ] Findings grid columns, badges, and bulk actions captured. +- [ ] Explain drawer walkthrough includes rule chain, evidence, and raw trace. +- [ ] Simulation diff behaviour and CLI callouts described. +- [ ] Exports (immediate and scheduled) plus webhook integration covered. +- [ ] Real-time updates, metrics, and error correlation documented. +- [ ] Offline behaviour and screenshot coordination noted. +- [ ] References validated. + +--- + +*Last updated: 2025-10-26 (Sprint 23).* + diff --git a/docs/ui/policies.md b/docs/ui/policies.md index 3378a563..878141b9 100644 --- a/docs/ui/policies.md +++ b/docs/ui/policies.md @@ -1,192 +1,192 @@ -# StellaOps Console - Policies Workspace - -> **Audience:** Policy Guild, Console UX, product ops, review leads. -> **Scope:** Policy workspace navigation, editor surfaces, simulation, approvals, RBAC, observability, offline behaviour, and CLI parity for Sprint 23. - -The Policies workspace centralises authoring, simulation, review, and promotion for `stella-dsl@1` packs. It builds on the Policy Editor (`docs/ui/policy-editor.md`) and adds list views, governance workflows, and integrations with runs and findings. - ---- - -## 1. Access and prerequisites - -- **Routes:** - - `/console/policies` (list) - - `/console/policies/:policyId` (details) - - `/console/policies/:policyId/:revision` (editor, approvals, runs) -- **Scopes / roles:** - - `policy:read` (list and details) - - `policy:author` (edit drafts, run lint/compile) - - `policy:review`, `policy:approve` (workflow actions) - - `policy:operate` (promotions, run orchestration) - - `policy:simulate` (run simulations) - - `policy:audit` (download audit bundles) - - `effective:write` (promotion visibility only; actual write remains server-side) -- **Feature flags:** `policy.studio.enabled`, `policy.simulation.diff`, `policy.runCharts.enabled`, `policy.offline.bundleUpload`. -- **Dependencies:** Policy Engine v2 APIs (`/policies`, `/policy/runs`, `/policy/simulations`), Policy Studio Monaco assets, Authority fresh-auth flows for critical operations. - ---- - -## 2. List and detail views - -### 2.1 Policy list - -| Column | Description | -|--------|-------------| -| **Policy** | Human-readable name plus policy ID (e.g., `P-7`). | -| **State** | `Active`, `Draft`, `Staged`, `Simulation`, `Archived`. Badge colours align with Policy Engine status. | -| **Revision** | Latest revision digest (short SHA). | -| **Owner** | Primary maintainer or owning team tag. | -| **Last change** | Timestamp and actor of last update (edit, submit, approve). | -| **Pending approvals** | Count of outstanding approval requests (with tooltip listing reviewers). | - -Row actions: `Open`, `Duplicate`, `Export pack`, `Run simulation`, `Compare revisions`. - -Filters: owning team, state, tag, pending approvals, contains staged changes, last change window, simulation warnings (determinism, failed run). - -### 2.2 Policy detail header - -- Summary cards: current state, digest, active revision, staged revision (if any), simulation status, last production run (timestamp, duration, determinism hash). -- Action bar: `Edit draft`, `Run simulation`, `Submit for review`, `Promote`, `Export pack`, `View findings`. - ---- - -## 3. Editor shell - -The editor view reuses the structure documented in `/docs/ui/policy-editor.md` and adds: - -- **Context banner** showing tenant, policy ID, revision digest, and simulation badge if editing sandbox copy. -- **Lint and compile status** displayed inline with time since last run. -- **Checklist sidebar** summarising required steps (lint pass, simulation run, deterministic CI, security review). Each item links to evidence (e.g., latest simulation diff). -- **Monaco integration** with policy-specific snippets, schema hover, code actions (`Insert allowlist`, `Add justification`). -- **Draft autosave** every 30 seconds with conflict detection (merges disabled; last write wins with warning). - ---- - -## 4. Simulation workflows - -- Simulation modal accepts SBOM filter (golden set, specific SBOM IDs, tenant-wide) and options for VEX weighting overrides. -- Simulations run asynchronously; progress shown in run ticker with status updates. -- Diff view summarises totals: affected findings added/removed, severity up/down counts, quieted changes. -- Side-by-side diff (Active vs Simulation) accessible directly from policy detail. -- Export options: JSON diff, Markdown summary, CLI snippet `stella policy simulate --policy --sbom `. -- Simulation results cached per draft revision. Cache invalidates when draft changes or SBOM snapshot updates. -- Simulation compliance card requires at least one up-to-date simulation before submission. - ---- - -## 5. Review and approval - -- **Review requests:** Authors tag reviewers; review sidebar lists pending reviewers, due dates, and escalation contact. -- **Comments:** Threaded comments support markdown, mentions, and attachments (redacted before persistence). Comment resolution required before approval. -- **Approval checklist:** - - Lint/compile success - - Simulation fresh (within configured SLA) - - Determinism verification passed - - Security review (if flagged) - - Offline bundle prepared (optional) -- **Fresh-auth:** Approve/promote buttons require fresh authentication; modal prompts for credentials and enforces short-lived token (<5 minutes). -- **Approval audit:** Approval events recorded with correlation ID, digests, reviewer note, effective date, and optional ticket link. - ---- - -## 6. Promotion and rollout - -- Promotion dialog summarises staged changes, target tenants, release windows, and run plan (full vs incremental). -- Operators can schedule promotion or apply immediately. -- Promotion triggers Policy Engine to materialise new revision; console reflects status and shows run progress. -- CLI parity: `stella policy promote --policy --revision --run-mode full`. -- Rollback guidance accessible from action bar (`Open rollback instructions`) linking to CLI command and documentation. - ---- - -## 7. Runs and observability - -- Runs tab displays table of recent runs with columns: run ID, type (`full`, `incremental`, `simulation`), duration, determinism hash, findings delta counts, triggered by. -- Charts: findings trend, quieted findings trend, rule hit heatmap (top rules vs recent runs). -- Clicking a run opens run detail drawer showing inputs (policy digest, SBOM batch hash, advisory snapshot hash), output summary, and explain bundle download. -- Error runs display red badge; detail drawer includes correlation ID and link to Policy Engine logs. -- SSE updates stream run status changes to keep UI real-time. - ---- - -## 8. RBAC and governance - -| Role | Scopes | Capabilities | -|------|--------|--------------| -| **Author** | `policy:read`, `policy:author`, `policy:simulate` | Create drafts, run lint/simulations, comment. | -| **Reviewer** | `policy:read`, `policy:review`, `policy:simulate` | Leave review comments, request changes. | -| **Approver** | `policy:read`, `policy:approve`, `policy:operate`, `policy:simulate` | Approve/promote, trigger runs, view run history. | -| **Operator** | `policy:read`, `policy:operate`, `policy:simulate`, `effective:write` | Schedule promotions, monitor runs (no editing). | -| **Auditor** | `policy:read`, `policy:audit`, `policy:simulate` | View immutable history, export audit bundles. | -| **Admin** | Above plus Authority admin scopes | Manage roles, configure escalation chains. | - -UI disables controls not allowed by current scope and surfaces tooltip with required scope names. Audit log captures denied attempts (`policy.ui.action_denied`). - ---- - -## 9. Exports and offline bundles - -- `Export pack` button downloads policy pack (zip) with metadata, digest manifest, and README. -- Offline bundle uploader allows importing reviewed packs; UI verifies signatures and digests before applying. -- Explain bundle export collects latest run explain traces for audit. -- CLI parity: - - `stella policy export --policy --revision ` - - `stella policy bundle import --file ` - - `stella policy bundle export --policy --revision ` -- Offline mode displays banner and disables direct promotion; provides script instructions for offline runner. - ---- - -## 10. Observability and alerts - -- Metrics cards show `policy_run_seconds`, `policy_rules_fired_total`, `policy_determinism_failures_total`. -- Alert banners surfaced for determinism failures, simulation stale warnings, approval SLA breaches. -- Links to dashboards (Grafana) pre-filtered with policy ID. -- Telemetry panel lists last emitted events (policy.promoted, policy.simulation.completed). - ---- - -## 11. Offline and air-gap considerations - -- In sealed mode, editor warns about cached enrichment data; simulation run button adds tooltip explaining degraded evidence. -- Promotions queue and require manual CLI execution on authorised host; UI provides downloadable job manifest. -- Run charts switch to snapshot data; SSE streams disabled, replaced by manual refresh button. -- Export/download buttons label file paths for removable media transfer. - ---- - -## 12. Screenshot coordination - -- Placeholders: - - `![Policy list placeholder](../assets/ui/policies/list-placeholder.png)` - - `![Policy approval placeholder](../assets/ui/policies/approval-placeholder.png)` - - `![Simulation diff placeholder](../assets/ui/policies/simulation-placeholder.png)` -- Coordinate with Console Guild via `#console-screenshots` (entry 2025-10-26) to replace placeholders once UI captures are ready (light and dark themes). - ---- - -## 13. References - -- `/docs/ui/policy-editor.md` - detailed editor mechanics. -- `/docs/ui/findings.md` - downstream findings view and explain drawer. -- `/docs/policy/overview.md` and `/docs/policy/runs.md` - Policy Engine contracts. -- `/docs/security/authority-scopes.md` - scope definitions. -- `/docs/cli/policy.md` - CLI commands for policy management. -- `/docs/ui/console-overview.md` - navigation shell and filters. - ---- - -## 14. Compliance checklist - -- [ ] Policy list and detail workflow documented (columns, filters, actions). -- [ ] Editor shell extends Policy Studio guidance with checklists and lint/simulation integration. -- [ ] Simulation flow, diff presentation, and CLI parity captured. -- [ ] Review, approval, and promotion workflows detailed with scope gating. -- [ ] Runs dashboard, metrics, and SSE behaviour described. -- [ ] Exports and offline bundle handling included. -- [ ] Offline/air-gap behaviour and screenshot coordination recorded. -- [ ] References validated. - ---- - -*Last updated: 2025-10-26 (Sprint 23).* +# StellaOps Console - Policies Workspace + +> **Audience:** Policy Guild, Console UX, product ops, review leads. +> **Scope:** Policy workspace navigation, editor surfaces, simulation, approvals, RBAC, observability, offline behaviour, and CLI parity for Sprint 23. + +The Policies workspace centralises authoring, simulation, review, and promotion for `stella-dsl@1` packs. It builds on the Policy Editor (`docs/ui/policy-editor.md`) and adds list views, governance workflows, and integrations with runs and findings. + +--- + +## 1. Access and prerequisites + +- **Routes:** + - `/console/policies` (list) + - `/console/policies/:policyId` (details) + - `/console/policies/:policyId/:revision` (editor, approvals, runs) +- **Scopes / roles:** + - `policy:read` (list and details) + - `policy:author` (edit drafts, run lint/compile) + - `policy:review`, `policy:approve` (workflow actions) + - `policy:operate` (promotions, run orchestration) + - `policy:simulate` (run simulations) + - `policy:audit` (download audit bundles) + - `effective:write` (promotion visibility only; actual write remains server-side) +- **Feature flags:** `policy.studio.enabled`, `policy.simulation.diff`, `policy.runCharts.enabled`, `policy.offline.bundleUpload`. +- **Dependencies:** Policy Engine v2 APIs (`/policies`, `/policy/runs`, `/policy/simulations`), Policy Studio Monaco assets, Authority fresh-auth flows for critical operations. + +--- + +## 2. List and detail views + +### 2.1 Policy list + +| Column | Description | +|--------|-------------| +| **Policy** | Human-readable name plus policy ID (e.g., `P-7`). | +| **State** | `Active`, `Draft`, `Staged`, `Simulation`, `Archived`. Badge colours align with Policy Engine status. | +| **Revision** | Latest revision digest (short SHA). | +| **Owner** | Primary maintainer or owning team tag. | +| **Last change** | Timestamp and actor of last update (edit, submit, approve). | +| **Pending approvals** | Count of outstanding approval requests (with tooltip listing reviewers). | + +Row actions: `Open`, `Duplicate`, `Export pack`, `Run simulation`, `Compare revisions`. + +Filters: owning team, state, tag, pending approvals, contains staged changes, last change window, simulation warnings (determinism, failed run). + +### 2.2 Policy detail header + +- Summary cards: current state, digest, active revision, staged revision (if any), simulation status, last production run (timestamp, duration, determinism hash). +- Action bar: `Edit draft`, `Run simulation`, `Submit for review`, `Promote`, `Export pack`, `View findings`. + +--- + +## 3. Editor shell + +The editor view reuses the structure documented in `/docs/ui/policy-editor.md` and adds: + +- **Context banner** showing tenant, policy ID, revision digest, and simulation badge if editing sandbox copy. +- **Lint and compile status** displayed inline with time since last run. +- **Checklist sidebar** summarising required steps (lint pass, simulation run, deterministic CI, security review). Each item links to evidence (e.g., latest simulation diff). +- **Monaco integration** with policy-specific snippets, schema hover, code actions (`Insert allowlist`, `Add justification`). +- **Draft autosave** every 30 seconds with conflict detection (merges disabled; last write wins with warning). + +--- + +## 4. Simulation workflows + +- Simulation modal accepts SBOM filter (golden set, specific SBOM IDs, tenant-wide) and options for VEX weighting overrides. +- Simulations run asynchronously; progress shown in run ticker with status updates. +- Diff view summarises totals: affected findings added/removed, severity up/down counts, quieted changes. +- Side-by-side diff (Active vs Simulation) accessible directly from policy detail. +- Export options: JSON diff, Markdown summary, CLI snippet `stella policy simulate --policy --sbom `. +- Simulation results cached per draft revision. Cache invalidates when draft changes or SBOM snapshot updates. +- Simulation compliance card requires at least one up-to-date simulation before submission. + +--- + +## 5. Review and approval + +- **Review requests:** Authors tag reviewers; review sidebar lists pending reviewers, due dates, and escalation contact. +- **Comments:** Threaded comments support markdown, mentions, and attachments (redacted before persistence). Comment resolution required before approval. +- **Approval checklist:** + - Lint/compile success + - Simulation fresh (within configured SLA) + - Determinism verification passed + - Security review (if flagged) + - Offline bundle prepared (optional) +- **Fresh-auth:** Approve/promote buttons require fresh authentication; modal prompts for credentials and enforces short-lived token (<5 minutes). +- **Approval audit:** Approval events recorded with correlation ID, digests, reviewer note, effective date, and optional ticket link. + +--- + +## 6. Promotion and rollout + +- Promotion dialog summarises staged changes, target tenants, release windows, and run plan (full vs incremental). +- Operators can schedule promotion or apply immediately. +- Promotion triggers Policy Engine to materialise new revision; console reflects status and shows run progress. +- CLI parity: `stella policy promote --policy --revision --run-mode full`. +- Rollback guidance accessible from action bar (`Open rollback instructions`) linking to CLI command and documentation. + +--- + +## 7. Runs and observability + +- Runs tab displays table of recent runs with columns: run ID, type (`full`, `incremental`, `simulation`), duration, determinism hash, findings delta counts, triggered by. +- Charts: findings trend, quieted findings trend, rule hit heatmap (top rules vs recent runs). +- Clicking a run opens run detail drawer showing inputs (policy digest, SBOM batch hash, advisory snapshot hash), output summary, and explain bundle download. +- Error runs display red badge; detail drawer includes correlation ID and link to Policy Engine logs. +- SSE updates stream run status changes to keep UI real-time. + +--- + +## 8. RBAC and governance + +| Role | Scopes | Capabilities | +|------|--------|--------------| +| **Author** | `policy:read`, `policy:author`, `policy:simulate` | Create drafts, run lint/simulations, comment. | +| **Reviewer** | `policy:read`, `policy:review`, `policy:simulate` | Leave review comments, request changes. | +| **Approver** | `policy:read`, `policy:approve`, `policy:operate`, `policy:simulate` | Approve/promote, trigger runs, view run history. | +| **Operator** | `policy:read`, `policy:operate`, `policy:simulate`, `effective:write` | Schedule promotions, monitor runs (no editing). | +| **Auditor** | `policy:read`, `policy:audit`, `policy:simulate` | View immutable history, export audit bundles. | +| **Admin** | Above plus Authority admin scopes | Manage roles, configure escalation chains. | + +UI disables controls not allowed by current scope and surfaces tooltip with required scope names. Audit log captures denied attempts (`policy.ui.action_denied`). + +--- + +## 9. Exports and offline bundles + +- `Export pack` button downloads policy pack (zip) with metadata, digest manifest, and README. +- Offline bundle uploader allows importing reviewed packs; UI verifies signatures and digests before applying. +- Explain bundle export collects latest run explain traces for audit. +- CLI parity: + - `stella policy export --policy --revision ` + - `stella policy bundle import --file ` + - `stella policy bundle export --policy --revision ` +- Offline mode displays banner and disables direct promotion; provides script instructions for offline runner. + +--- + +## 10. Observability and alerts + +- Metrics cards show `policy_run_seconds`, `policy_rules_fired_total`, `policy_determinism_failures_total`. +- Alert banners surfaced for determinism failures, simulation stale warnings, approval SLA breaches. +- Links to dashboards (Grafana) pre-filtered with policy ID. +- Telemetry panel lists last emitted events (policy.promoted, policy.simulation.completed). + +--- + +## 11. Offline and air-gap considerations + +- In sealed mode, editor warns about cached enrichment data; simulation run button adds tooltip explaining degraded evidence. +- Promotions queue and require manual CLI execution on authorised host; UI provides downloadable job manifest. +- Run charts switch to snapshot data; SSE streams disabled, replaced by manual refresh button. +- Export/download buttons label file paths for removable media transfer. + +--- + +## 12. Screenshot coordination + +- Placeholders: + - `![Policy list placeholder](../assets/ui/policies/list-placeholder.png)` + - `![Policy approval placeholder](../assets/ui/policies/approval-placeholder.png)` + - `![Simulation diff placeholder](../assets/ui/policies/simulation-placeholder.png)` +- Coordinate with Console Guild via `#console-screenshots` (entry 2025-10-26) to replace placeholders once UI captures are ready (light and dark themes). + +--- + +## 13. References + +- `/docs/ui/policy-editor.md` - detailed editor mechanics. +- `/docs/ui/findings.md` - downstream findings view and explain drawer. +- `/docs/policy/overview.md` and `/docs/policy/runs.md` - Policy Engine contracts. +- `/docs/security/authority-scopes.md` - scope definitions. +- `/docs/modules/cli/guides/policy.md` - CLI commands for policy management. +- `/docs/ui/console-overview.md` - navigation shell and filters. + +--- + +## 14. Compliance checklist + +- [ ] Policy list and detail workflow documented (columns, filters, actions). +- [ ] Editor shell extends Policy Studio guidance with checklists and lint/simulation integration. +- [ ] Simulation flow, diff presentation, and CLI parity captured. +- [ ] Review, approval, and promotion workflows detailed with scope gating. +- [ ] Runs dashboard, metrics, and SSE behaviour described. +- [ ] Exports and offline bundle handling included. +- [ ] Offline/air-gap behaviour and screenshot coordination recorded. +- [ ] References validated. + +--- + +*Last updated: 2025-10-26 (Sprint 23).* diff --git a/docs/ui/policy-editor.md b/docs/ui/policy-editor.md index f8f8b77b..441d5ccd 100644 --- a/docs/ui/policy-editor.md +++ b/docs/ui/policy-editor.md @@ -1,179 +1,179 @@ -# Policy Editor Workspace - -> **Audience:** Product/UX, UI engineers, policy authors/reviewers using the Console. -> **Scope:** Layout, features, RBAC, a11y, simulation workflow, approvals, run dashboards, and offline considerations for the Policy Engine v2 editor (“Policy Studio”). - -The Policy Editor is the primary Console workspace for composing, simulating, and approving `stella-dsl@1` policies. It combines Monaco-based editing, diff visualisations, and governance tools so authors and reviewers can collaborate without leaving the browser. - ---- - -## 1 · Access & Prerequisites - -- **Routes:** `/console/policy` (list) → `/console/policy/:policyId/:version?`. -- **Scopes / roles:** - - `policy:author` (role `policy-author`) to edit drafts, run lint/compile, and execute quick simulations. - - `policy:review` (role `policy-reviewer`) to review drafts, leave comments, and request changes. - - `policy:approve` (role `policy-approver`) to approve or reject submissions. - - `policy:operate` (role `policy-operator`) to trigger batch simulations, promotions, and canary runs. - - `policy:audit` (role `policy-auditor`) to access immutable history and audit exports. - - `policy:simulate` to run simulations from Console; `findings:read` to open explain drawers. -- **Feature flags:** `policyStudio.enabled` (defaults true once Policy Engine v2 API available). -- **Browser support:** Evergreen Chrome, Edge, Firefox, Safari (last two versions). Uses WASM OPA sandbox; ensure COOP/COEP enabled per [UI architecture](../ARCHITECTURE_UI.md). - ---- - -## 2 · Workspace Layout - -``` -┌────────────────────────────────────────────────────────────────────────────┐ -│ Header: Policy selector • tenant switch • last activation banner │ -├────────────────────────────────────────────────────────────────────────────┤ -│ Sidebar (left) │ Main content (right) │ -│ - Revision list │ ┌───────────── Editor tabs ───────────────┐ │ -│ - Checklist status │ │ DSL │ Simulation │ Approvals │ ... │ │ -│ - Pending reviews │ └─────────────────────────────────────────┘ │ -│ - Run backlog │ │ -│ │ Editor pane / Simulation diff / Run viewer │ -└────────────────────────────────────────────────────────────────────────────┘ -``` - -- **Sidebar:** Revision timeline (draft, submitted, approved), compliance checklist cards, outstanding review requests, run backlog (incremental queue depth and SLA). -- **Editor tabs:** - - *DSL* (primary Monaco editor) - - *Simulation* (pre/post diff charts) - - *Approvals* (comments, audit log) - - *Runs* (heatmap dashboards) - - *Explain Explorer* (optional drawer for findings) -- **Right rail:** context cards for VEX providers, policy metadata, quick links to CLI/API docs. - -> Placeholder screenshot: `![Policy editor workspace](../assets/policy-editor/workspace.png)` (add after UI team captures latest build). - ---- - -## 3 · Editing Experience - -- Monaco editor configured for `stella-dsl@1`: - - Syntax highlighting, IntelliSense for rule/action names, snippets for common patterns. - - Inline diagnostics sourced from `/policies/{id}/lint` and `/compile`. - - Code actions (“Fix indentation”, “Insert requireVex block”). - - Mini-map disabled by default to reduce contrast noise; toggle available. -- **Keyboard shortcuts (accessible via `?`):** - - `Ctrl/Cmd + S` – Save draft (uploads to API if changed). - - `Ctrl/Cmd + Shift + Enter` – Run lint + compile. - - `Ctrl/Cmd + Shift + D` – Open diff view vs baseline. - - `Alt + Shift + F` – Format document (canonical ordering). -- **Schema tooltips:** Hover on `profile`, `rule`, `action` to view documentation (sourced from DSL doc). -- **Offline warnings:** When `sealed` mode detected, banner reminds authors to validate with offline bundle. - ---- - -## 4 · Simulation & Diff Panel - -- Triggered via “Run simulation” (toolbar) or automatically after compile. -- Displays: - - **Summary cards:** total findings added/removed/unchanged; severity up/down counts. - - **Rule hit table:** top rules contributing to diffs with percentage change. - - **Component list:** virtualised table linking to explain drawer; supports filters (severity, status, VEX outcome). - - **Visualisations:** stacked bar chart (severity deltas), sparkline for incremental backlog impact. -- Supports run presets: - - `Golden SBOM set` (default) - - Custom SBOM selection (via multi-select and search) - - Import sample JSON from CLI (`Upload diff`). -- Diff export options: - - `Download JSON` (same schema as CLI output) - - `Copy as Markdown` for review comments -- Simulation results persist per draft version; history accessible via timeline. - ---- - -## 5 · Review & Approval Workflow - -- **Commenting:** Line-level comments anchored to DSL lines; global comments supported. Uses rich text (Markdown subset) with mention support (`@group/sec-reviewers`). -- **Resolution:** Approvers/reviewers can mark comment resolved; history preserved in timeline. -- **Approval pane:** - - Checklist (lint, simulation, determinism CI) with status indicators; links to evidence. - - Reviewer checklist (quorum, blocking comments). - - Approval button only enabled when checklist satisfied. -- **Audit log:** Chronological view of submit/review/approve/archive events with actor, timestamp, note, attachments. -- **RBAC feedback:** When user lacks permission, actions are disabled with tooltip referencing required scope(s). -- **Notifications:** Integration with Notifier—subscribe/unsubscribe from review reminders within panel. - ---- - -## 6 · Runs & Observability - -- **Run tab** consumes `/policy/runs` data: - - Heatmap of rule hits per run (rows = runs, columns = top rules). - - VEX override counter, suppressions, quieted findings metrics. - - Incremental backlog widget (queue depth vs SLA). - - Export CSV/JSON button. -- **Replay/Download:** For each run, actions to download sealed replay bundle or open CLI command snippet. -- **Alert banners:** - - Determinism mismatch (red) - - SLA breach (amber) - - Pending replay (info) - ---- - -## 7 · Explain & Findings Integration - -- Inline “Open in Findings” button for any diff entry; opens side drawer with explain trace (same schema as `/findings/*/explain`). -- Drawer includes: - - Rule sequence with badges (block/warn/quiet). - - VEX evidence and justification codes. - - Links to advisories (Concelier) and SBOM components. -- Copy-to-clipboard (JSON) and “Share permalink” features (permalinks encode tenant, policy version, component). - ---- - -## 8 · Accessibility & i18n - -- WCAG 2.2 AA: - - Focus order follows logical workflow; skip link available. - - All actionable icons paired with text or `aria-label`. - - Simulation charts include table equivalents for screen readers. -- Keyboard support: - - `Alt+1/2/3/4` to switch tabs. - - `Shift+?` toggles help overlay (with key map). -- Internationalisation: - - Translations sourced from `/locales/{lang}.json`. - - Date/time displayed using user locale via `Intl.DateTimeFormat`. -- Theming: - - Light/dark CSS tokens; Monaco theme syncs with overall theme. - - High-contrast mode toggled via user preferences. - ---- - -## 9 · Offline & Air-Gap Behaviour - -- When console operates in sealed enclave: - - Editor displays “Sealed mode” banner with import timestamp. - - Simulation uses cached SBOM/advisory/VEX data only; results flagged accordingly. - - “Export bundle” button packages draft + simulations for transfer. -- Approvals require local Authority; UI blocks actions if `policy:approve` scope absent due to offline token limitations. -- Run tab surfaces bundle staleness warnings (`policy_runs.inputs.env.sealed=true`). - ---- - -## 10 · Telemetry & Testing Hooks - -- User actions (simulate, submit, approve, activate) emit telemetry (`ui.policy.action` spans) with anonymised metadata. -- Console surfaces correlation IDs for lint/compile errors to ease support triage. -- Cypress/Playwright fixtures available under `ui/policy-editor/examples/`; docs should note to re-record after significant UI changes. - ---- - -## 11 · Compliance Checklist - -- [ ] **Lint integration:** Editor surfaces diagnostics from API compile endpoint; errors link to DSL documentation. -- [ ] **Simulation parity:** Diff panel mirrors CLI schema; export button tested. -- [ ] **Workflow RBAC:** Buttons enable/disable correctly per scope (`policy:write/submit/review/approve`). -- [ ] **A11y verified:** Keyboard navigation, focus management, colour contrast (light/dark) pass automated Axe checks. -- [ ] **Offline safeguards:** Sealed-mode banner and bundle export flows present; no network calls trigger in sealed mode. -- [ ] **Telemetry wired:** Action spans and error logs include policyId, version, traceId. -- [ ] **Docs cross-links:** Links to DSL, lifecycle, runs, API, CLI guides validated. -- [ ] **Screenshot placeholders updated:** Replace TODO images with latest UI captures before GA. - ---- - -*Last updated: 2025-10-26 (Sprint 20).* +# Policy Editor Workspace + +> **Audience:** Product/UX, UI engineers, policy authors/reviewers using the Console. +> **Scope:** Layout, features, RBAC, a11y, simulation workflow, approvals, run dashboards, and offline considerations for the Policy Engine v2 editor (“Policy Studio”). + +The Policy Editor is the primary Console workspace for composing, simulating, and approving `stella-dsl@1` policies. It combines Monaco-based editing, diff visualisations, and governance tools so authors and reviewers can collaborate without leaving the browser. + +--- + +## 1 · Access & Prerequisites + +- **Routes:** `/console/policy` (list) → `/console/policy/:policyId/:version?`. +- **Scopes / roles:** + - `policy:author` (role `policy-author`) to edit drafts, run lint/compile, and execute quick simulations. + - `policy:review` (role `policy-reviewer`) to review drafts, leave comments, and request changes. + - `policy:approve` (role `policy-approver`) to approve or reject submissions. + - `policy:operate` (role `policy-operator`) to trigger batch simulations, promotions, and canary runs. + - `policy:audit` (role `policy-auditor`) to access immutable history and audit exports. + - `policy:simulate` to run simulations from Console; `findings:read` to open explain drawers. +- **Feature flags:** `policyStudio.enabled` (defaults true once Policy Engine v2 API available). +- **Browser support:** Evergreen Chrome, Edge, Firefox, Safari (last two versions). Uses WASM OPA sandbox; ensure COOP/COEP enabled per [UI architecture](../modules/ui/architecture.md). + +--- + +## 2 · Workspace Layout + +``` +┌────────────────────────────────────────────────────────────────────────────┐ +│ Header: Policy selector • tenant switch • last activation banner │ +├────────────────────────────────────────────────────────────────────────────┤ +│ Sidebar (left) │ Main content (right) │ +│ - Revision list │ ┌───────────── Editor tabs ───────────────┐ │ +│ - Checklist status │ │ DSL │ Simulation │ Approvals │ ... │ │ +│ - Pending reviews │ └─────────────────────────────────────────┘ │ +│ - Run backlog │ │ +│ │ Editor pane / Simulation diff / Run viewer │ +└────────────────────────────────────────────────────────────────────────────┘ +``` + +- **Sidebar:** Revision timeline (draft, submitted, approved), compliance checklist cards, outstanding review requests, run backlog (incremental queue depth and SLA). +- **Editor tabs:** + - *DSL* (primary Monaco editor) + - *Simulation* (pre/post diff charts) + - *Approvals* (comments, audit log) + - *Runs* (heatmap dashboards) + - *Explain Explorer* (optional drawer for findings) +- **Right rail:** context cards for VEX providers, policy metadata, quick links to CLI/API docs. + +> Placeholder screenshot: `![Policy editor workspace](../assets/policy-editor/workspace.png)` (add after UI team captures latest build). + +--- + +## 3 · Editing Experience + +- Monaco editor configured for `stella-dsl@1`: + - Syntax highlighting, IntelliSense for rule/action names, snippets for common patterns. + - Inline diagnostics sourced from `/policies/{id}/lint` and `/compile`. + - Code actions (“Fix indentation”, “Insert requireVex block”). + - Mini-map disabled by default to reduce contrast noise; toggle available. +- **Keyboard shortcuts (accessible via `?`):** + - `Ctrl/Cmd + S` – Save draft (uploads to API if changed). + - `Ctrl/Cmd + Shift + Enter` – Run lint + compile. + - `Ctrl/Cmd + Shift + D` – Open diff view vs baseline. + - `Alt + Shift + F` – Format document (canonical ordering). +- **Schema tooltips:** Hover on `profile`, `rule`, `action` to view documentation (sourced from DSL doc). +- **Offline warnings:** When `sealed` mode detected, banner reminds authors to validate with offline bundle. + +--- + +## 4 · Simulation & Diff Panel + +- Triggered via “Run simulation” (toolbar) or automatically after compile. +- Displays: + - **Summary cards:** total findings added/removed/unchanged; severity up/down counts. + - **Rule hit table:** top rules contributing to diffs with percentage change. + - **Component list:** virtualised table linking to explain drawer; supports filters (severity, status, VEX outcome). + - **Visualisations:** stacked bar chart (severity deltas), sparkline for incremental backlog impact. +- Supports run presets: + - `Golden SBOM set` (default) + - Custom SBOM selection (via multi-select and search) + - Import sample JSON from CLI (`Upload diff`). +- Diff export options: + - `Download JSON` (same schema as CLI output) + - `Copy as Markdown` for review comments +- Simulation results persist per draft version; history accessible via timeline. + +--- + +## 5 · Review & Approval Workflow + +- **Commenting:** Line-level comments anchored to DSL lines; global comments supported. Uses rich text (Markdown subset) with mention support (`@group/sec-reviewers`). +- **Resolution:** Approvers/reviewers can mark comment resolved; history preserved in timeline. +- **Approval pane:** + - Checklist (lint, simulation, determinism CI) with status indicators; links to evidence. + - Reviewer checklist (quorum, blocking comments). + - Approval button only enabled when checklist satisfied. +- **Audit log:** Chronological view of submit/review/approve/archive events with actor, timestamp, note, attachments. +- **RBAC feedback:** When user lacks permission, actions are disabled with tooltip referencing required scope(s). +- **Notifications:** Integration with Notifier—subscribe/unsubscribe from review reminders within panel. + +--- + +## 6 · Runs & Observability + +- **Run tab** consumes `/policy/runs` data: + - Heatmap of rule hits per run (rows = runs, columns = top rules). + - VEX override counter, suppressions, quieted findings metrics. + - Incremental backlog widget (queue depth vs SLA). + - Export CSV/JSON button. +- **Replay/Download:** For each run, actions to download sealed replay bundle or open CLI command snippet. +- **Alert banners:** + - Determinism mismatch (red) + - SLA breach (amber) + - Pending replay (info) + +--- + +## 7 · Explain & Findings Integration + +- Inline “Open in Findings” button for any diff entry; opens side drawer with explain trace (same schema as `/findings/*/explain`). +- Drawer includes: + - Rule sequence with badges (block/warn/quiet). + - VEX evidence and justification codes. + - Links to advisories (Concelier) and SBOM components. +- Copy-to-clipboard (JSON) and “Share permalink” features (permalinks encode tenant, policy version, component). + +--- + +## 8 · Accessibility & i18n + +- WCAG 2.2 AA: + - Focus order follows logical workflow; skip link available. + - All actionable icons paired with text or `aria-label`. + - Simulation charts include table equivalents for screen readers. +- Keyboard support: + - `Alt+1/2/3/4` to switch tabs. + - `Shift+?` toggles help overlay (with key map). +- Internationalisation: + - Translations sourced from `/locales/{lang}.json`. + - Date/time displayed using user locale via `Intl.DateTimeFormat`. +- Theming: + - Light/dark CSS tokens; Monaco theme syncs with overall theme. + - High-contrast mode toggled via user preferences. + +--- + +## 9 · Offline & Air-Gap Behaviour + +- When console operates in sealed enclave: + - Editor displays “Sealed mode” banner with import timestamp. + - Simulation uses cached SBOM/advisory/VEX data only; results flagged accordingly. + - “Export bundle” button packages draft + simulations for transfer. +- Approvals require local Authority; UI blocks actions if `policy:approve` scope absent due to offline token limitations. +- Run tab surfaces bundle staleness warnings (`policy_runs.inputs.env.sealed=true`). + +--- + +## 10 · Telemetry & Testing Hooks + +- User actions (simulate, submit, approve, activate) emit telemetry (`ui.policy.action` spans) with anonymised metadata. +- Console surfaces correlation IDs for lint/compile errors to ease support triage. +- Cypress/Playwright fixtures available under `ui/policy-editor/examples/`; docs should note to re-record after significant UI changes. + +--- + +## 11 · Compliance Checklist + +- [ ] **Lint integration:** Editor surfaces diagnostics from API compile endpoint; errors link to DSL documentation. +- [ ] **Simulation parity:** Diff panel mirrors CLI schema; export button tested. +- [ ] **Workflow RBAC:** Buttons enable/disable correctly per scope (`policy:write/submit/review/approve`). +- [ ] **A11y verified:** Keyboard navigation, focus management, colour contrast (light/dark) pass automated Axe checks. +- [ ] **Offline safeguards:** Sealed-mode banner and bundle export flows present; no network calls trigger in sealed mode. +- [ ] **Telemetry wired:** Action spans and error logs include policyId, version, traceId. +- [ ] **Docs cross-links:** Links to DSL, lifecycle, runs, API, CLI guides validated. +- [ ] **Screenshot placeholders updated:** Replace TODO images with latest UI captures before GA. + +--- + +*Last updated: 2025-10-26 (Sprint 20).* diff --git a/docs/ui/runs.md b/docs/ui/runs.md index 14a140d4..f4c011fb 100644 --- a/docs/ui/runs.md +++ b/docs/ui/runs.md @@ -1,169 +1,169 @@ -# StellaOps Console - Runs Workspace - -> **Audience:** Scheduler Guild, Console UX, operators, support engineers. -> **Scope:** Runs dashboard, live progress, queue management, diffs, retries, evidence downloads, observability, troubleshooting, and offline behaviour (Sprint 23). - -The Runs workspace surfaces Scheduler activity across tenants: upcoming schedules, active runs, progress, deltas, and evidence bundles. It helps operators monitor backlog, drill into run segments, and recover from failures without leaving the console. - ---- - -## 1. Access and prerequisites - -- **Route:** `/console/runs` (list) with detail drawer `/console/runs/:runId`. SSE stream at `/console/runs/:runId/stream`. -- **Scopes:** `runs.read` (baseline), `runs.manage` (cancel/retry), `policy:runs` (view policy deltas), `downloads.read` (evidence bundles). -- **Dependencies:** Scheduler WebService (`/runs`, `/schedules`, `/preview`), Scheduler Worker event feeds, Policy Engine run summaries, Scanner WebService evidence endpoints. -- **Feature flags:** `runs.dashboard.enabled`, `runs.sse.enabled`, `runs.retry.enabled`, `runs.evidenceBundles`. -- **Tenancy:** Tenant selector filters list; cross-tenant admins can pin multiple tenants side-by-side (split view). - ---- - -## 2. Layout overview - -``` -+-------------------------------------------------------------------+ -| Header: Tenant badge - schedule selector - backlog metrics | -+-------------------------------------------------------------------+ -| Cards: Active runs - Queue depth - New findings - KEV deltas | -+-------------------------------------------------------------------+ -| Tabs: Active | Completed | Scheduled | Failures | -+-------------------------------------------------------------------+ -| Runs table (virtualised) | -| Columns: Run ID | Trigger | State | Progress | Duration | Deltas | -+-------------------------------------------------------------------+ -| Detail drawer: Summary | Segments | Deltas | Evidence | Logs | -+-------------------------------------------------------------------+ -``` - -The header integrates the status ticker to show ingestion deltas and planner heartbeat. - ---- - -## 3. Runs table - -| Column | Description | -|--------|-------------| -| **Run ID** | Deterministic identifier (`run:::`). Clicking opens detail drawer. | -| **Trigger** | `cron`, `manual`, `feedser`, `vexer`, `policy`, `content-refresh`. Tooltip lists schedule and initiator. | -| **State** | Badges: `planning`, `queued`, `running`, `completed`, `cancelled`, `error`. Errors include error code (e.g., `ERR_RUN_005`). | -| **Progress** | Percentage + processed/total candidates. SSE updates increment in real time. | -| **Duration** | Elapsed time (auto-updating). Completed runs show total duration; running runs show timer. | -| **Deltas** | Count of findings deltas (`+critical`, `+high`, `-quieted`, etc.). Tooltip expands severity breakdown. | - -Row badges include `KEV first`, `Content refresh`, `Policy promotion follow-up`, and `Retry`. Selecting multiple rows enables bulk downloads and exports. - -Filters: trigger type, state, schedule, severity impact (critical/high), policy revision, timeframe, planner shard, error code. - ---- - -## 4. Detail drawer - -Sections: - -1. **Summary** - run metadata (tenant, trigger, linked schedule, planner shard count, started/finished timestamps, correlation ID). -2. **Progress** - segmented progress bar (planner, queue, execution, post-processing). Real-time updates via SSE; includes throughput (targets per minute). -3. **Segments** - table of run segments with state, target count, executor, retry count. Operators can retry failed segments individually (requires `runs.manage`). -4. **Deltas** - summary of findings changes (new findings, resolved findings, severity shifts, KEV additions). Links to Findings view filtered by run ID. -5. **Evidence** - links to evidence bundles (JSON manifest, DSSE attestation), policy run records, and explain bundles. Download buttons use `/console/exports` orchestration. -6. **Logs** - last 50 structured log entries with severity, message, correlation ID; scroll-to-live for streaming logs. `Open in logs` copies query for external log tooling. - ---- - -## 5. Queue and schedule management - -- Schedule side panel lists upcoming jobs with cron expressions, time zones, and enable toggles. -- Queue depth chart shows current backlog per tenant and schedule (planner backlog, executor backlog). -- "Preview impact" button opens modal for manual run planning (purls or vuln IDs) and shows impacted image count before launch. CLI parity: `stella runs preview --tenant --file keys.json`. -- Manual run form allows selecting mode (`analysis-only`, `content-refresh`), scope, and optional policy snapshot. -- Pausing a schedule requires confirmation; UI displays earliest next run after resume. - ---- - -## 6. Live updates and SSE stream - -- SSE endpoint `/console/runs/{id}/stream` streams JSON events (`stateChanged`, `segmentProgress`, `deltaSummary`, `log`). UI reconnects with exponential backoff and heartbeat. -- Global ticker shows planner heartbeat age; banner warns after 90 seconds of silence. -- Offline mode disables SSE and falls back to polling every 30 seconds. - ---- - -## 7. Retry and remediation - -- Failed segments show retry button; UI displays reason and cooldown timers. Retry actions are scope-gated and logged. -- Full run retry resets segments while preserving original run metadata; new run ID references previous run in `retryOf` field. -- "Escalate to support" button opens incident template pre-filled with run context and correlation IDs. -- Troubleshooting quick links: - - `ERR_RUN_001` (planner lock) - - `ERR_RUN_005` (Scanner timeout) - - `ERR_RUN_009` (impact index stale) - Each link points to corresponding runbook sections (`docs/ops/scheduler-runbook.md`). -- CLI parity: `stella runs retry --run `, `stella runs cancel --run `. - ---- - -## 8. Evidence downloads - -- Evidence tab aggregates: - - Policy run summary (`/policy/runs/{id}`) - - Findings delta CSV (`/downloads/findings/{runId}.csv`) - - Scanner evidence bundle (compressed JSON with manifest) -- Downloads show size, hash, signature status. -- "Bundle for offline" packages all evidence into single tarball with manifest/digest; UI notes CLI parity (`stella runs export --run --bundle`). -- Completed bundles stored in Downloads workspace for reuse (links provided). - ---- - -## 9. Observability - -- Metrics cards: `scheduler_queue_depth`, `scheduler_runs_active`, `scheduler_runs_error_total`, `scheduler_runs_duration_seconds`. -- Trend charts: queue depth (last 24h), runs per trigger, average duration, determinism score. -- Alert banners: planner lag > SLA, queue depth > threshold, repeated error codes. -- Telemetry panel lists latest events (e.g., `scheduler.run.started`, `scheduler.run.completed`, `scheduler.run.failed`). - ---- - -## 10. Offline and air-gap behaviour - -- Offline banner highlights snapshot timestamp and indicates SSE disabled. -- Manual run form switches to generate CLI script for offline execution (`stella runs submit --bundle `). -- Evidence download buttons output local paths; UI reminds to copy to removable media. -- Queue charts use snapshot data; manual refresh button loads latest records from Offline Kit. -- Tenants absent from snapshot hidden to avoid partial data. - ---- - -## 11. Screenshot coordination - -- Placeholders: - - `![Runs dashboard placeholder](../assets/ui/runs/dashboard-placeholder.png)` - - `![Run detail placeholder](../assets/ui/runs/detail-placeholder.png)` -- Coordinate with Scheduler Guild for updated screenshots after Sprint 23 UI stabilises (tracked in `#console-screenshots`, entry 2025-10-26). - ---- - -## 12. References - -- `/docs/ui/console-overview.md` - shell, SSE ticker. -- `/docs/ui/navigation.md` - route map and deep links. -- `/docs/ui/findings.md` - findings filtered by run. -- `/docs/ui/downloads.md` - download manager, export retention, CLI parity. -- `/docs/ARCHITECTURE_SCHEDULER.md` - scheduler architecture and data model. -- `/docs/policy/runs.md` - policy run integration. -- `/docs/cli/policy.md` and `/docs/cli/policy.md` section 5 for CLI parity (runs commands pending). -- `/docs/ops/scheduler-runbook.md` - troubleshooting. - ---- - -## 13. Compliance checklist - -- [ ] Runs table columns, filters, and states described. -- [ ] Detail drawer sections documented (segments, deltas, evidence, logs). -- [ ] Queue management, manual run, and preview coverage included. -- [ ] SSE and live update behaviour detailed. -- [ ] Retry, remediation, and runbook references provided. -- [ ] Evidence downloads and bundle workflows documented with CLI parity. -- [ ] Offline behaviour and screenshot coordination recorded. -- [ ] References validated. - ---- - -*Last updated: 2025-10-26 (Sprint 23).* +# StellaOps Console - Runs Workspace + +> **Audience:** Scheduler Guild, Console UX, operators, support engineers. +> **Scope:** Runs dashboard, live progress, queue management, diffs, retries, evidence downloads, observability, troubleshooting, and offline behaviour (Sprint 23). + +The Runs workspace surfaces Scheduler activity across tenants: upcoming schedules, active runs, progress, deltas, and evidence bundles. It helps operators monitor backlog, drill into run segments, and recover from failures without leaving the console. + +--- + +## 1. Access and prerequisites + +- **Route:** `/console/runs` (list) with detail drawer `/console/runs/:runId`. SSE stream at `/console/runs/:runId/stream`. +- **Scopes:** `runs.read` (baseline), `runs.manage` (cancel/retry), `policy:runs` (view policy deltas), `downloads.read` (evidence bundles). +- **Dependencies:** Scheduler WebService (`/runs`, `/schedules`, `/preview`), Scheduler Worker event feeds, Policy Engine run summaries, Scanner WebService evidence endpoints. +- **Feature flags:** `runs.dashboard.enabled`, `runs.sse.enabled`, `runs.retry.enabled`, `runs.evidenceBundles`. +- **Tenancy:** Tenant selector filters list; cross-tenant admins can pin multiple tenants side-by-side (split view). + +--- + +## 2. Layout overview + +``` ++-------------------------------------------------------------------+ +| Header: Tenant badge - schedule selector - backlog metrics | ++-------------------------------------------------------------------+ +| Cards: Active runs - Queue depth - New findings - KEV deltas | ++-------------------------------------------------------------------+ +| Tabs: Active | Completed | Scheduled | Failures | ++-------------------------------------------------------------------+ +| Runs table (virtualised) | +| Columns: Run ID | Trigger | State | Progress | Duration | Deltas | ++-------------------------------------------------------------------+ +| Detail drawer: Summary | Segments | Deltas | Evidence | Logs | ++-------------------------------------------------------------------+ +``` + +The header integrates the status ticker to show ingestion deltas and planner heartbeat. + +--- + +## 3. Runs table + +| Column | Description | +|--------|-------------| +| **Run ID** | Deterministic identifier (`run:::`). Clicking opens detail drawer. | +| **Trigger** | `cron`, `manual`, `feedser`, `vexer`, `policy`, `content-refresh`. Tooltip lists schedule and initiator. | +| **State** | Badges: `planning`, `queued`, `running`, `completed`, `cancelled`, `error`. Errors include error code (e.g., `ERR_RUN_005`). | +| **Progress** | Percentage + processed/total candidates. SSE updates increment in real time. | +| **Duration** | Elapsed time (auto-updating). Completed runs show total duration; running runs show timer. | +| **Deltas** | Count of findings deltas (`+critical`, `+high`, `-quieted`, etc.). Tooltip expands severity breakdown. | + +Row badges include `KEV first`, `Content refresh`, `Policy promotion follow-up`, and `Retry`. Selecting multiple rows enables bulk downloads and exports. + +Filters: trigger type, state, schedule, severity impact (critical/high), policy revision, timeframe, planner shard, error code. + +--- + +## 4. Detail drawer + +Sections: + +1. **Summary** - run metadata (tenant, trigger, linked schedule, planner shard count, started/finished timestamps, correlation ID). +2. **Progress** - segmented progress bar (planner, queue, execution, post-processing). Real-time updates via SSE; includes throughput (targets per minute). +3. **Segments** - table of run segments with state, target count, executor, retry count. Operators can retry failed segments individually (requires `runs.manage`). +4. **Deltas** - summary of findings changes (new findings, resolved findings, severity shifts, KEV additions). Links to Findings view filtered by run ID. +5. **Evidence** - links to evidence bundles (JSON manifest, DSSE attestation), policy run records, and explain bundles. Download buttons use `/console/exports` orchestration. +6. **Logs** - last 50 structured log entries with severity, message, correlation ID; scroll-to-live for streaming logs. `Open in logs` copies query for external log tooling. + +--- + +## 5. Queue and schedule management + +- Schedule side panel lists upcoming jobs with cron expressions, time zones, and enable toggles. +- Queue depth chart shows current backlog per tenant and schedule (planner backlog, executor backlog). +- "Preview impact" button opens modal for manual run planning (purls or vuln IDs) and shows impacted image count before launch. CLI parity: `stella runs preview --tenant --file keys.json`. +- Manual run form allows selecting mode (`analysis-only`, `content-refresh`), scope, and optional policy snapshot. +- Pausing a schedule requires confirmation; UI displays earliest next run after resume. + +--- + +## 6. Live updates and SSE stream + +- SSE endpoint `/console/runs/{id}/stream` streams JSON events (`stateChanged`, `segmentProgress`, `deltaSummary`, `log`). UI reconnects with exponential backoff and heartbeat. +- Global ticker shows planner heartbeat age; banner warns after 90 seconds of silence. +- Offline mode disables SSE and falls back to polling every 30 seconds. + +--- + +## 7. Retry and remediation + +- Failed segments show retry button; UI displays reason and cooldown timers. Retry actions are scope-gated and logged. +- Full run retry resets segments while preserving original run metadata; new run ID references previous run in `retryOf` field. +- "Escalate to support" button opens incident template pre-filled with run context and correlation IDs. +- Troubleshooting quick links: + - `ERR_RUN_001` (planner lock) + - `ERR_RUN_005` (Scanner timeout) + - `ERR_RUN_009` (impact index stale) + Each link points to corresponding runbook sections (`docs/modules/scheduler/operations/worker.md`). +- CLI parity: `stella runs retry --run `, `stella runs cancel --run `. + +--- + +## 8. Evidence downloads + +- Evidence tab aggregates: + - Policy run summary (`/policy/runs/{id}`) + - Findings delta CSV (`/downloads/findings/{runId}.csv`) + - Scanner evidence bundle (compressed JSON with manifest) +- Downloads show size, hash, signature status. +- "Bundle for offline" packages all evidence into single tarball with manifest/digest; UI notes CLI parity (`stella runs export --run --bundle`). +- Completed bundles stored in Downloads workspace for reuse (links provided). + +--- + +## 9. Observability + +- Metrics cards: `scheduler_queue_depth`, `scheduler_runs_active`, `scheduler_runs_error_total`, `scheduler_runs_duration_seconds`. +- Trend charts: queue depth (last 24h), runs per trigger, average duration, determinism score. +- Alert banners: planner lag > SLA, queue depth > threshold, repeated error codes. +- Telemetry panel lists latest events (e.g., `scheduler.run.started`, `scheduler.run.completed`, `scheduler.run.failed`). + +--- + +## 10. Offline and air-gap behaviour + +- Offline banner highlights snapshot timestamp and indicates SSE disabled. +- Manual run form switches to generate CLI script for offline execution (`stella runs submit --bundle `). +- Evidence download buttons output local paths; UI reminds to copy to removable media. +- Queue charts use snapshot data; manual refresh button loads latest records from Offline Kit. +- Tenants absent from snapshot hidden to avoid partial data. + +--- + +## 11. Screenshot coordination + +- Placeholders: + - `![Runs dashboard placeholder](../assets/ui/runs/dashboard-placeholder.png)` + - `![Run detail placeholder](../assets/ui/runs/detail-placeholder.png)` +- Coordinate with Scheduler Guild for updated screenshots after Sprint 23 UI stabilises (tracked in `#console-screenshots`, entry 2025-10-26). + +--- + +## 12. References + +- `/docs/ui/console-overview.md` - shell, SSE ticker. +- `/docs/ui/navigation.md` - route map and deep links. +- `/docs/ui/findings.md` - findings filtered by run. +- `/docs/ui/downloads.md` - download manager, export retention, CLI parity. +- `/docs/modules/scheduler/architecture.md` - scheduler architecture and data model. +- `/docs/policy/runs.md` - policy run integration. +- `/docs/modules/cli/guides/policy.md` and `/docs/modules/cli/guides/policy.md` section 5 for CLI parity (runs commands pending). +- `/docs/modules/scheduler/operations/worker.md` - troubleshooting. + +--- + +## 13. Compliance checklist + +- [ ] Runs table columns, filters, and states described. +- [ ] Detail drawer sections documented (segments, deltas, evidence, logs). +- [ ] Queue management, manual run, and preview coverage included. +- [ ] SSE and live update behaviour detailed. +- [ ] Retry, remediation, and runbook references provided. +- [ ] Evidence downloads and bundle workflows documented with CLI parity. +- [ ] Offline behaviour and screenshot coordination recorded. +- [ ] References validated. + +--- + +*Last updated: 2025-10-26 (Sprint 23).* diff --git a/docs/ui/sbom-explorer.md b/docs/ui/sbom-explorer.md index 6137fe4f..74f22473 100644 --- a/docs/ui/sbom-explorer.md +++ b/docs/ui/sbom-explorer.md @@ -1,195 +1,195 @@ -# StellaOps Console - SBOM Explorer - -> **Audience:** Console UX, SBOM Service Guild, enablement teams, customer onboarding. -> **Scope:** Catalog listing, component detail, graph overlays, exports, performance hints, and offline behaviour for the SBOM Explorer that ships in Sprint 23. - -The SBOM Explorer lets operators inspect software bills of materials collected by Scanner and normalised by the SBOM Service. It provides tenant-scoped catalogs, usage overlays, provenance-aware graphs, and deterministic export paths that align with CLI workflows. - ---- - -## 1. Access and prerequisites - -- **Routes:** `/console/sbom` (catalog) and `/console/sbom/:digest` (detail). -- **Scopes:** `sbom.read` (required), `sbom.export` for large export jobs, `findings.read` to open explain drawers, `policy.read` to view overlay metadata. -- **Feature flags:** `sbomExplorer.enabled` (default true when SBOM Service v3 API is enabled) and `graph.overlays.enabled` for Cartographer-backed overlays. -- **Tenant scoping:** All queries include `tenant` tokens; switching tenants triggers catalog refetch and clears cached overlays. -- **Data dependencies:** Requires SBOM Service 3.1+ with Cartographer overlays and Policy Engine explain hints enabled. - ---- - -## 2. Layout overview - -``` -+-----------------------------------------------------------------------+ -| Header: Tenant badge - global filters - offline indicator - actions | -+-----------------------------------------------------------------------+ -| Left rail: Saved views - pinned tags - export queue status | -+-----------------------------------------------------------------------+ -| Catalog table (virtualised) | -| - Columns: Image digest - Source - Scan timestamp - Policy verdict | -| - Badges: Delta SBOM, Attested, Offline snapshot | -+-----------------------------------------------------------------------+ -| Detail drawer or full page tabs (Inventory | Usage | Components | | -| Overlays | Explain | Exports) | -+-----------------------------------------------------------------------+ -``` - -The catalog and detail views reuse the shared command palette, context chips, and SSE status ticker described in `/docs/ui/navigation.md`. - ---- - -## 3. Catalog view - -| Feature | Description | -|---------|-------------| -| **Virtual table** | Uses Angular CDK virtual scroll to render up to 10,000 records per tenant without layout jank. Sorting and filtering are client-side for <= 20k rows; the UI upgrades to server-side queries automatically when more records exist. | -| **Preset segments** | Quick toggles for `All`, `Recent (7 d)`, `Delta-ready`, `Attested`, and `Offline snapshots`. Each preset maps to saved view tokens for CLI parity. | -| **Search** | Global search field supports image digests, repository tags, SBOM IDs, and component PURLs. Search terms propagate to the detail view when opened. | -| **Badges** | - `Delta` badge indicates SBOM produced via delta mode (layers reuse).
- `Attested` badge links to Attestor proof and Rekor record.
- `Snapshot` badge shows offline import hash.
- `Policy` badge references last policy verdict summary. | -| **Bulk actions** | Multi-select rows to stage export jobs, trigger async explain generation, or copy CLI commands. Actions enforce per-tenant rate limits and show authority scopes in tooltips. | - ---- - -## 4. Detail tabs - -### 4.1 Inventory tab - -- Default view summarising all components with columns for package name (PURL), version, supplier, license, size, and counts of referencing layers. -- Filters: severity, ecosystem (OS, NPM, PyPI, Maven, Go, NuGet, Rust, containers), usage flag (true/false), package tags. -- Sorting: by severity (desc), version (asc), supplier. -- Cell tooltips reference Concelier advisories and Policy Engine findings when available. -- Total component count, unique suppliers, and critical severity counts appear in the header cards. - -### 4.2 Usage tab - -- Focuses on runtime usage (EntryTrace, runtime sensors, allow lists). -- Columns include process names, entry points, and `usedByEntrypoint` flags. -- Grouping: by entry point, by package, or by namespace (Kubernetes). -- Highlights mismatches between declared dependencies and observed usage for drift detection. - -### 4.3 Components tab - -- Deep dive for a single component selected from Inventory or Usage. -- Shows provenance timeline (introduced in layer, modified, removed), file paths, cryptographic hashes, and linked evidence (DSSE, Attestor bundles). -- Links to CLI commands: `stella sbom component show ` and `stella sbom component export`. -- Drawer supports multi-component comparison through tabbed interface. - -### 4.4 Overlays tab - -- Displays Cartographer overlays: vulnerability overlays (policy verdicts), runtime overlays (process traces), and vendor advisories. -- Each overlay card lists source, generation timestamp, precedence, and staleness relative to tenant SLA. -- Toggle overlays on/off to see impact on component status; UI does not mutate canonical SBOM, it only enriches the view. -- Graph preview button opens force-directed component graph (limited to <= 500 nodes) with filters for dependency depth and relationship type. -- Overlay metadata includes the CLI parity snippet: `stella sbom overlay apply --overlay --digest `. - -### 4.5 Explain tab - -- Integrates Policy Engine explain drawer. -- Shows rule hits, VEX overrides, and evidence per component. -- Provides "Open in Findings" link that preserves tenant and filters. - -### 4.6 Exports tab - -- Lists available exports (CycloneDX JSON, CycloneDX Protobuf, SPDX JSON, SPDX Tag-Value, Delta bundle, Evidence bundle). -- Each export entry shows size, hash (SHA-256), format version, and generation time. -- Download buttons respect RBAC and offline quotas; CLI callouts mirror `stella sbom export`. -- "Schedule export" launches async job for large bundles; job status integrates with `/console/downloads`. -- Includes copy-to-clipboard path for offline transfers (`/offline-kits/export///`). - ---- - -## 5. Filters and presets - -| Filter | Applies to | Notes | -|--------|------------|-------| -| **Severity** | Inventory, Overlays, Explain | Uses Policy Engine severity buckets and KEV flag. | -| **Ecosystem** | Inventory, Usage | Multi-select list with search; maps to package type derived from PURL. | -| **License** | Inventory | Groups by SPDX identifiers; warns on copyleft obligations. | -| **Supplier** | Inventory, Components | Autocomplete backed by SBOM metadata. | -| **Tags** | Inventory, Usage | Tags provided by Scanner or user-defined metadata. | -| **Component search** | Components, Overlays | Accepts PURL or substring; retains highlight when switching tabs. | -| **Snapshot** | Catalog | Filters to SBOMs sourced from Offline Kit or local import. | -| **Attested only** | Catalog, Exports | Limits to SBOMs signed by Attestor; displays Rekor badge. | - -Saved views store combinations of these filters and expose command palette shortcuts (`Cmd+1-9 / Ctrl+1-9`). - ---- - -## 6. Graph overlays and cartography - -- Graph view is powered by Cartographer projections (tenant-scoped graph snapshots). -- Supported overlays: - - **Dependency graph** (default) - nodes represent components, edges represent dependencies with direction (introducer -> introduced). - - **Runtime call graph** - optional overlay layering process calls on top of dependencies. - - **Vulnerability overlay** - colours nodes by highest severity and outlines exploited components. -- Controls: depth slider (1-6), include transitive flag, hide dev dependencies toggle, highlight vendor-specified critical paths. -- Export options: GraphML, JSON Lines, and screenshot capture (requires `graph.export`). -- Performance guardrails: overlays warn when node count exceeds 2,000; user can queue background job to render static graph for download instead. - ---- - -## 7. Exports and automation - -- **Instant exports:** Inline downloads for CycloneDX JSON/Protobuf (<= 25 MB) and SPDX JSON (<= 25 MB). -- **Async exports:** Larger bundles stream through the download manager with resume support. UI polls `/console/downloads` every 15 seconds while export is in progress. -- **CLI parity:** Each export card displays the equivalent CLI command and environment variables (proxy, offline). -- **Compliance metadata:** Export manifests include SBOM ID, component count, hash, signature state, and policy verdict summary so auditors can validate offline. -- **Automation hooks:** Webhook button copies the `/downloads/hooks/subscribe` call for integration with CI pipelines. - ---- - -## 8. Performance tips - -- Virtual scroll keeps initial render under 70 ms for 10k rows; server-side pagination engages beyond that threshold. -- Graph overlay rendering uses Web Workers to keep main thread responsive; heavy layouts show "Background layout in progress" banner. -- SSE updates (new SBOM ready) refresh header cards and prepend rows without full table redraw. -- Prefetching: opening a detail drawer preloads overlays and exports concurrently; these requests cancel automatically if the user navigates away. -- Local cache (IndexedDB) stores last viewed SBOM detail for each tenant (up to 20 entries). Cache invalidates when new merge hash is observed. - ---- - -## 9. Offline and air-gap behaviour - -- Catalog reads from Offline Kit snapshot if gateway is in sealed mode; offline banner lists snapshot ID and staleness. -- Overlays limited to data included in snapshot; missing overlays show guidance to import updated Cartographer package. -- Exports queue locally and generate tarballs ready to copy to removable media. -- CLI parity callouts switch to offline examples (using `stella sbom export --offline`). -- Tenants unavailable in snapshot are hidden from the tenant picker to prevent inconsistent views. - ---- - -## 10. Screenshot coordination - -- Placeholder images: - - `![SBOM catalog view placeholder](../assets/ui/sbom/catalog-placeholder.png)` - - `![Overlay graph placeholder](../assets/ui/sbom/overlay-placeholder.png)` -- Coordinate with Console Guild to capture updated screenshots (dark and light theme) once Sprint 23 UI stabilises. Track follow-up in Console Guild thread `#console-screenshots` dated 2025-10-26. - ---- - -## 11. References - -- `/docs/ui/console-overview.md` - navigation shell, tenant model, filters. -- `/docs/ui/navigation.md` - command palette, deep-link schema. -- `/docs/ui/downloads.md` - download queue, manifest parity, offline export handling. -- `/docs/security/console-security.md` - scopes, DPoP, CSP. -- `/docs/cli-vs-ui-parity.md` - CLI equivalence matrix. -- `/docs/architecture/console.md` (pending) - component data flows. -- `/docs/architecture/overview.md` - high-level module relationships. -- `/docs/ingestion/aggregation-only-contract.md` - provenance and guard rails. - ---- - -## 12. Compliance checklist - -- [ ] Catalog table and detail tabs documented with columns, filters, and presets. -- [ ] Overlay behaviour describes Cartographer integration and CLI parity. -- [ ] Export section includes instant vs async workflow and compliance metadata. -- [ ] Performance considerations align with UI benchmarks (virtual scroll, workers). -- [ ] Offline behaviour captured for catalog, overlays, exports. -- [ ] Screenshot placeholders and coordination notes recorded with Console Guild follow-up. -- [ ] All referenced docs verified and accessible. - ---- - -*Last updated: 2025-10-26 (Sprint 23).* +# StellaOps Console - SBOM Explorer + +> **Audience:** Console UX, SBOM Service Guild, enablement teams, customer onboarding. +> **Scope:** Catalog listing, component detail, graph overlays, exports, performance hints, and offline behaviour for the SBOM Explorer that ships in Sprint 23. + +The SBOM Explorer lets operators inspect software bills of materials collected by Scanner and normalised by the SBOM Service. It provides tenant-scoped catalogs, usage overlays, provenance-aware graphs, and deterministic export paths that align with CLI workflows. + +--- + +## 1. Access and prerequisites + +- **Routes:** `/console/sbom` (catalog) and `/console/sbom/:digest` (detail). +- **Scopes:** `sbom.read` (required), `sbom.export` for large export jobs, `findings.read` to open explain drawers, `policy.read` to view overlay metadata. +- **Feature flags:** `sbomExplorer.enabled` (default true when SBOM Service v3 API is enabled) and `graph.overlays.enabled` for Cartographer-backed overlays. +- **Tenant scoping:** All queries include `tenant` tokens; switching tenants triggers catalog refetch and clears cached overlays. +- **Data dependencies:** Requires SBOM Service 3.1+ with Cartographer overlays and Policy Engine explain hints enabled. + +--- + +## 2. Layout overview + +``` ++-----------------------------------------------------------------------+ +| Header: Tenant badge - global filters - offline indicator - actions | ++-----------------------------------------------------------------------+ +| Left rail: Saved views - pinned tags - export queue status | ++-----------------------------------------------------------------------+ +| Catalog table (virtualised) | +| - Columns: Image digest - Source - Scan timestamp - Policy verdict | +| - Badges: Delta SBOM, Attested, Offline snapshot | ++-----------------------------------------------------------------------+ +| Detail drawer or full page tabs (Inventory | Usage | Components | | +| Overlays | Explain | Exports) | ++-----------------------------------------------------------------------+ +``` + +The catalog and detail views reuse the shared command palette, context chips, and SSE status ticker described in `/docs/ui/navigation.md`. + +--- + +## 3. Catalog view + +| Feature | Description | +|---------|-------------| +| **Virtual table** | Uses Angular CDK virtual scroll to render up to 10,000 records per tenant without layout jank. Sorting and filtering are client-side for <= 20k rows; the UI upgrades to server-side queries automatically when more records exist. | +| **Preset segments** | Quick toggles for `All`, `Recent (7 d)`, `Delta-ready`, `Attested`, and `Offline snapshots`. Each preset maps to saved view tokens for CLI parity. | +| **Search** | Global search field supports image digests, repository tags, SBOM IDs, and component PURLs. Search terms propagate to the detail view when opened. | +| **Badges** | - `Delta` badge indicates SBOM produced via delta mode (layers reuse).
- `Attested` badge links to Attestor proof and Rekor record.
- `Snapshot` badge shows offline import hash.
- `Policy` badge references last policy verdict summary. | +| **Bulk actions** | Multi-select rows to stage export jobs, trigger async explain generation, or copy CLI commands. Actions enforce per-tenant rate limits and show authority scopes in tooltips. | + +--- + +## 4. Detail tabs + +### 4.1 Inventory tab + +- Default view summarising all components with columns for package name (PURL), version, supplier, license, size, and counts of referencing layers. +- Filters: severity, ecosystem (OS, NPM, PyPI, Maven, Go, NuGet, Rust, containers), usage flag (true/false), package tags. +- Sorting: by severity (desc), version (asc), supplier. +- Cell tooltips reference Concelier advisories and Policy Engine findings when available. +- Total component count, unique suppliers, and critical severity counts appear in the header cards. + +### 4.2 Usage tab + +- Focuses on runtime usage (EntryTrace, runtime sensors, allow lists). +- Columns include process names, entry points, and `usedByEntrypoint` flags. +- Grouping: by entry point, by package, or by namespace (Kubernetes). +- Highlights mismatches between declared dependencies and observed usage for drift detection. + +### 4.3 Components tab + +- Deep dive for a single component selected from Inventory or Usage. +- Shows provenance timeline (introduced in layer, modified, removed), file paths, cryptographic hashes, and linked evidence (DSSE, Attestor bundles). +- Links to CLI commands: `stella sbom component show ` and `stella sbom component export`. +- Drawer supports multi-component comparison through tabbed interface. + +### 4.4 Overlays tab + +- Displays Cartographer overlays: vulnerability overlays (policy verdicts), runtime overlays (process traces), and vendor advisories. +- Each overlay card lists source, generation timestamp, precedence, and staleness relative to tenant SLA. +- Toggle overlays on/off to see impact on component status; UI does not mutate canonical SBOM, it only enriches the view. +- Graph preview button opens force-directed component graph (limited to <= 500 nodes) with filters for dependency depth and relationship type. +- Overlay metadata includes the CLI parity snippet: `stella sbom overlay apply --overlay --digest `. + +### 4.5 Explain tab + +- Integrates Policy Engine explain drawer. +- Shows rule hits, VEX overrides, and evidence per component. +- Provides "Open in Findings" link that preserves tenant and filters. + +### 4.6 Exports tab + +- Lists available exports (CycloneDX JSON, CycloneDX Protobuf, SPDX JSON, SPDX Tag-Value, Delta bundle, Evidence bundle). +- Each export entry shows size, hash (SHA-256), format version, and generation time. +- Download buttons respect RBAC and offline quotas; CLI callouts mirror `stella sbom export`. +- "Schedule export" launches async job for large bundles; job status integrates with `/console/downloads`. +- Includes copy-to-clipboard path for offline transfers (`/offline-kits/export///`). + +--- + +## 5. Filters and presets + +| Filter | Applies to | Notes | +|--------|------------|-------| +| **Severity** | Inventory, Overlays, Explain | Uses Policy Engine severity buckets and KEV flag. | +| **Ecosystem** | Inventory, Usage | Multi-select list with search; maps to package type derived from PURL. | +| **License** | Inventory | Groups by SPDX identifiers; warns on copyleft obligations. | +| **Supplier** | Inventory, Components | Autocomplete backed by SBOM metadata. | +| **Tags** | Inventory, Usage | Tags provided by Scanner or user-defined metadata. | +| **Component search** | Components, Overlays | Accepts PURL or substring; retains highlight when switching tabs. | +| **Snapshot** | Catalog | Filters to SBOMs sourced from Offline Kit or local import. | +| **Attested only** | Catalog, Exports | Limits to SBOMs signed by Attestor; displays Rekor badge. | + +Saved views store combinations of these filters and expose command palette shortcuts (`Cmd+1-9 / Ctrl+1-9`). + +--- + +## 6. Graph overlays and cartography + +- Graph view is powered by Cartographer projections (tenant-scoped graph snapshots). +- Supported overlays: + - **Dependency graph** (default) - nodes represent components, edges represent dependencies with direction (introducer -> introduced). + - **Runtime call graph** - optional overlay layering process calls on top of dependencies. + - **Vulnerability overlay** - colours nodes by highest severity and outlines exploited components. +- Controls: depth slider (1-6), include transitive flag, hide dev dependencies toggle, highlight vendor-specified critical paths. +- Export options: GraphML, JSON Lines, and screenshot capture (requires `graph.export`). +- Performance guardrails: overlays warn when node count exceeds 2,000; user can queue background job to render static graph for download instead. + +--- + +## 7. Exports and automation + +- **Instant exports:** Inline downloads for CycloneDX JSON/Protobuf (<= 25 MB) and SPDX JSON (<= 25 MB). +- **Async exports:** Larger bundles stream through the download manager with resume support. UI polls `/console/downloads` every 15 seconds while export is in progress. +- **CLI parity:** Each export card displays the equivalent CLI command and environment variables (proxy, offline). +- **Compliance metadata:** Export manifests include SBOM ID, component count, hash, signature state, and policy verdict summary so auditors can validate offline. +- **Automation hooks:** Webhook button copies the `/downloads/hooks/subscribe` call for integration with CI pipelines. + +--- + +## 8. Performance tips + +- Virtual scroll keeps initial render under 70 ms for 10k rows; server-side pagination engages beyond that threshold. +- Graph overlay rendering uses Web Workers to keep main thread responsive; heavy layouts show "Background layout in progress" banner. +- SSE updates (new SBOM ready) refresh header cards and prepend rows without full table redraw. +- Prefetching: opening a detail drawer preloads overlays and exports concurrently; these requests cancel automatically if the user navigates away. +- Local cache (IndexedDB) stores last viewed SBOM detail for each tenant (up to 20 entries). Cache invalidates when new merge hash is observed. + +--- + +## 9. Offline and air-gap behaviour + +- Catalog reads from Offline Kit snapshot if gateway is in sealed mode; offline banner lists snapshot ID and staleness. +- Overlays limited to data included in snapshot; missing overlays show guidance to import updated Cartographer package. +- Exports queue locally and generate tarballs ready to copy to removable media. +- CLI parity callouts switch to offline examples (using `stella sbom export --offline`). +- Tenants unavailable in snapshot are hidden from the tenant picker to prevent inconsistent views. + +--- + +## 10. Screenshot coordination + +- Placeholder images: + - `![SBOM catalog view placeholder](../assets/ui/sbom/catalog-placeholder.png)` + - `![Overlay graph placeholder](../assets/ui/sbom/overlay-placeholder.png)` +- Coordinate with Console Guild to capture updated screenshots (dark and light theme) once Sprint 23 UI stabilises. Track follow-up in Console Guild thread `#console-screenshots` dated 2025-10-26. + +--- + +## 11. References + +- `/docs/ui/console-overview.md` - navigation shell, tenant model, filters. +- `/docs/ui/navigation.md` - command palette, deep-link schema. +- `/docs/ui/downloads.md` - download queue, manifest parity, offline export handling. +- `/docs/security/console-security.md` - scopes, DPoP, CSP. +- `/docs/cli-vs-ui-parity.md` - CLI equivalence matrix. +- `/docs/architecture/console.md` (pending) - component data flows. +- `/docs/modules/platform/architecture-overview.md` - high-level module relationships. +- `/docs/ingestion/aggregation-only-contract.md` - provenance and guard rails. + +--- + +## 12. Compliance checklist + +- [ ] Catalog table and detail tabs documented with columns, filters, and presets. +- [ ] Overlay behaviour describes Cartographer integration and CLI parity. +- [ ] Export section includes instant vs async workflow and compliance metadata. +- [ ] Performance considerations align with UI benchmarks (virtual scroll, workers). +- [ ] Offline behaviour captured for catalog, overlays, exports. +- [ ] Screenshot placeholders and coordination notes recorded with Console Guild follow-up. +- [ ] All referenced docs verified and accessible. + +--- + +*Last updated: 2025-10-26 (Sprint 23).* diff --git a/docs/updates/2025-10-22-docs-guild.md b/docs/updates/2025-10-22-docs-guild.md index 177a7c3b..0138cb65 100644 --- a/docs/updates/2025-10-22-docs-guild.md +++ b/docs/updates/2025-10-22-docs-guild.md @@ -1,13 +1,13 @@ -# Docs Guild Update — 2025-10-22 - -**Subject:** Concelier Authority toggle rollout polish -**Audience:** Docs Guild, Concelier WebService Guild, Authority Core - -- Added a rollout phase table to `docs/10_CONCELIER_CLI_QUICKSTART.md`, clarifying how `authority.enabled` and `authority.allowAnonymousFallback` move from validation to enforced mode and highlighting the audit/metric signals to watch at each step. -- Extended the Authority integration checklist in the same quickstart so operators tie CLI smoke tests to audit counters before flipping enforcement. -- Refreshed `docs/ops/concelier-authority-audit-runbook.md` with the latest date stamp, prerequisites, and pre-check guidance that reference the quickstart timeline; keeps change-request templates aligned. -- Documented the new Go analyzer artefacts in `docs/24_OFFLINE_KIT.md` (manifest excerpt + tarball smoke test) so Ops can confirm the plug-in ships in the 2025‑10‑22 bundle before promoting it to mirrors. - -Next steps: -- Concelier WebService owners to link this update in the next deployment bulletin once FEEDWEB-DOCS-01-001 clears review. -- Docs Guild to verify the Offline Kit doc bundle picks up the quickstart/runbook changes after the nightly build. +# Docs Guild Update — 2025-10-22 + +**Subject:** Concelier Authority toggle rollout polish +**Audience:** Docs Guild, Concelier WebService Guild, Authority Core + +- Added a rollout phase table to `docs/10_CONCELIER_CLI_QUICKSTART.md`, clarifying how `authority.enabled` and `authority.allowAnonymousFallback` move from validation to enforced mode and highlighting the audit/metric signals to watch at each step. +- Extended the Authority integration checklist in the same quickstart so operators tie CLI smoke tests to audit counters before flipping enforcement. +- Refreshed `docs/modules/concelier/operations/authority-audit-runbook.md` with the latest date stamp, prerequisites, and pre-check guidance that reference the quickstart timeline; keeps change-request templates aligned. +- Documented the new Go analyzer artefacts in `docs/24_OFFLINE_KIT.md` (manifest excerpt + tarball smoke test) so Ops can confirm the plug-in ships in the 2025‑10‑22 bundle before promoting it to mirrors. + +Next steps: +- Concelier WebService owners to link this update in the next deployment bulletin once FEEDWEB-DOCS-01-001 clears review. +- Docs Guild to verify the Offline Kit doc bundle picks up the quickstart/runbook changes after the nightly build. diff --git a/docs/updates/2025-10-29-export-center-provenance.md b/docs/updates/2025-10-29-export-center-provenance.md index 35d63c46..5b258c41 100644 --- a/docs/updates/2025-10-29-export-center-provenance.md +++ b/docs/updates/2025-10-29-export-center-provenance.md @@ -1,9 +1,9 @@ -# 2025-10-29 – Export Center provenance/signing doc - -## Summary -- Authored `docs/export-center/provenance-and-signing.md`, covering manifest/provenance artefacts, cosign/SLSA signing pipeline, verification workflows (CLI/CI/offline), and compliance checklist. -- Cross-linked the new guide from the docs index (`docs/README.md`) and referenced outstanding CLI automation (`CLI-EXPORT-37-001`) to keep verification guidance aligned with upcoming tooling. - -## Follow-ups -- [ ] Revisit once `CLI-EXPORT-37-001` lands to confirm command names/flags and update the verification section if necessary. -- [ ] Sync with DevOps (`DEVOPS-EXPORT-37-001`) after dashboards/alerts ship to embed direct links in the failure handling section. +# 2025-10-29 – Export Center provenance/signing doc + +## Summary +- Authored `docs/modules/export-center/provenance-and-signing.md`, covering manifest/provenance artefacts, cosign/SLSA signing pipeline, verification workflows (CLI/CI/offline), and compliance checklist. +- Cross-linked the new guide from the docs index (`docs/README.md`) and referenced outstanding CLI automation (`CLI-EXPORT-37-001`) to keep verification guidance aligned with upcoming tooling. + +## Follow-ups +- [ ] Revisit once `CLI-EXPORT-37-001` lands to confirm command names/flags and update the verification section if necessary. +- [ ] Sync with DevOps (`DEVOPS-EXPORT-37-001`) after dashboards/alerts ship to embed direct links in the failure handling section. diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json deleted file mode 100644 index 3f1784de..00000000 --- a/node_modules/.package-lock.json +++ /dev/null @@ -1,267 +0,0 @@ -{ - "name": "git.stella-ops.org", - "lockfileVersion": 3, - "requires": true, - "packages": { - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-cli": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ajv-cli/-/ajv-cli-5.0.0.tgz", - "integrity": "sha512-LY4m6dUv44HTyhV+u2z5uX4EhPYTM38Iv1jdgDJJJCyOOuqB8KtZEGjPZ2T+sh5ZIJrXUfgErYx/j3gLd3+PlQ==", - "dependencies": { - "ajv": "^8.0.0", - "fast-json-patch": "^2.0.0", - "glob": "^7.1.0", - "js-yaml": "^3.14.0", - "json-schema-migrate": "^2.0.0", - "json5": "^2.1.3", - "minimist": "^1.2.0" - }, - "bin": { - "ajv": "dist/index.js" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/ajv-formats": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", - "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-patch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-2.2.1.tgz", - "integrity": "sha512-4j5uBaTnsYAV5ebkidvxiLUYOwjQ+JSFljeqfTxCrH9bDmlCQaOJFS84oDJ2rAXZq2yskmk3ORfoP9DCwqFNig==", - "dependencies": { - "fast-deep-equal": "^2.0.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/fast-json-patch/node_modules/fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ] - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-migrate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/json-schema-migrate/-/json-schema-migrate-2.0.0.tgz", - "integrity": "sha512-r38SVTtojDRp4eD6WsCqiE0eNDt4v1WalBXb9cyZYw9ai5cGtBwzRNWjHzJl38w6TxFkXAIA7h+fyX3tnrAFhQ==", - "dependencies": { - "ajv": "^8.0.0" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - } - } -} diff --git a/ops/deployment/AGENTS.md b/ops/deployment/AGENTS.md index 16730e7d..6b612418 100644 --- a/ops/deployment/AGENTS.md +++ b/ops/deployment/AGENTS.md @@ -1,4 +1,4 @@ -# Deployment & Operations — Agent Charter - -## Mission -Maintain deployment/upgrade/rollback workflows (Helm/Compose) per `docs/ARCHITECTURE_DEVOPS.md` including environment-specific configs. +# Deployment & Operations — Agent Charter + +## Mission +Maintain deployment/upgrade/rollback workflows (Helm/Compose) per `docs/modules/devops/ARCHITECTURE.md` including environment-specific configs. diff --git a/ops/devops/AGENTS.md b/ops/devops/AGENTS.md index bc640c47..8a80ede5 100644 --- a/ops/devops/AGENTS.md +++ b/ops/devops/AGENTS.md @@ -1,11 +1,11 @@ -# DevOps & Release — Agent Charter - -## Mission -Execute deterministic build/release pipeline per `docs/ARCHITECTURE_DEVOPS.md`: -- Reproducible builds with SBOM/provenance, cosign signing, transparency logging. -- Channel manifests (LTS/Stable/Edge) with digests, Helm/Compose profiles. -- Performance guard jobs ensuring budgets. - -## Expectations -- Coordinate with Scanner/Scheduler/Notify teams for artifact availability. -- Maintain CI reliability; update `TASKS.md` as states change. +# DevOps & Release — Agent Charter + +## Mission +Execute deterministic build/release pipeline per `docs/modules/devops/ARCHITECTURE.md`: +- Reproducible builds with SBOM/provenance, cosign signing, transparency logging. +- Channel manifests (LTS/Stable/Edge) with digests, Helm/Compose profiles. +- Performance guard jobs ensuring budgets. + +## Expectations +- Coordinate with Scanner/Scheduler/Notify teams for artifact availability. +- Maintain CI reliability; update `TASKS.md` as states change. diff --git a/ops/devops/README.md b/ops/devops/README.md index fd988aa7..a4a4841a 100644 --- a/ops/devops/README.md +++ b/ops/devops/README.md @@ -1,92 +1,92 @@ -# DevOps Release Automation - -The **release** workflow builds and signs the StellaOps service containers, -generates SBOM + provenance attestations, and emits a canonical -`release.yaml`. The logic lives under `ops/devops/release/` and is invoked -by the new `.gitea/workflows/release.yml` pipeline. - -## Local dry run - -```bash -./ops/devops/release/build_release.py \ - --version 2025.10.0-edge \ - --channel edge \ - --dry-run -``` - -Outputs land under `out/release/`. Use `--no-push` to run full builds without -pushing to the registry. - -After the build completes, run the verifier to validate recorded hashes and artefact -presence: - -```bash -python ops/devops/release/verify_release.py --release-dir out/release -``` - -## Python analyzer smoke & signing - -`dotnet run --project tools/LanguageAnalyzerSmoke` exercises the Python language -analyzer plug-in against the golden fixtures (cold/warm timings, determinism). The -release workflow runs this harness automatically and then produces Cosign -signatures + SHA-256 sidecars for `StellaOps.Scanner.Analyzers.Lang.Python.dll` -and its `manifest.json`. Keep `COSIGN_KEY_REF`/`COSIGN_IDENTITY_TOKEN` populated so -the step can sign the artefacts; the generated `.sig`/`.sha256` files ship with the -Offline Kit bundle. - -## Required tooling - -- Docker 25+ with Buildx -- .NET 10 preview SDK (builds container stages and the SBOM generator) -- Node.js 20 (Angular UI build) -- Helm 3.16+ -- Cosign 2.2+ - -Supply signing material via environment variables: - -- `COSIGN_KEY_REF` – e.g. `file:./keys/cosign.key` or `azurekms://…` -- `COSIGN_PASSWORD` – password protecting the above key - -The workflow defaults to multi-arch (`linux/amd64,linux/arm64`), SBOM in -CycloneDX, and SLSA provenance (`https://slsa.dev/provenance/v1`). - -## Debug store extraction - -`build_release.py` now exports stripped debug artefacts for every ELF discovered in the published images. The files land under `out/release/debug/.build-id//.debug`, with metadata captured in `debug/debug-manifest.json` (and a `.sha256` sidecar). Use `jq` to inspect the manifest or `readelf -n` to spot-check a build-id. Offline Kit packaging should reuse the `debug/` directory as-is. - -## UI auth smoke (Playwright) - -As part of **DEVOPS-UI-13-006** the pipelines will execute the UI auth smoke -tests (`npm run test:e2e`) after building the Angular bundle. See -`docs/ops/ui-auth-smoke.md` for the job design, environment stubs, and -offline runner considerations. - -## NuGet preview bootstrap - -`.NET 10` preview packages (Microsoft.Extensions.*, JwtBearer 10.0 RC, Sqlite 9 RC) -ship from the public `dotnet-public` Azure DevOps feed. We mirror them into -`./local-nuget` so restores succeed inside Offline Kit. - -1. Run `./ops/devops/sync-preview-nuget.sh` whenever you update the manifest. -2. The script now understands the optional `SourceBase` column (V3 flat container) - and writes packages alongside their SHA-256 checks. -3. `NuGet.config` registers the mirror (`local`), dotnet-public, and nuget.org. - -Use `python3 ops/devops/validate_restore_sources.py` to prove the repo still -prefers the local mirror and that `Directory.Build.props` enforces the same order. -The validator now runs automatically in the `build-test-deploy` and `release` -workflows so CI fails fast when a feed priority regression slips in. - -Detailed operator instructions live in `docs/ops/nuget-preview-bootstrap.md`. - -## Telemetry collector tooling (DEVOPS-OBS-50-001) - -- `ops/devops/telemetry/generate_dev_tls.sh` – generates a development CA and - client/server certificates for the OpenTelemetry collector overlay (mutual TLS). -- `ops/devops/telemetry/smoke_otel_collector.py` – sends OTLP traces/metrics/logs - over TLS and validates that the collector increments its receiver counters. -- `ops/devops/telemetry/package_offline_bundle.py` – re-packages collector assets for the Offline Kit. -- `deploy/compose/docker-compose.telemetry-storage.yaml` – Prometheus/Tempo/Loki stack for staging validation. - -Combine these helpers with `deploy/compose/docker-compose.telemetry.yaml` to run -a secured collector locally before rolling out the Helm-based deployment. +# DevOps Release Automation + +The **release** workflow builds and signs the StellaOps service containers, +generates SBOM + provenance attestations, and emits a canonical +`release.yaml`. The logic lives under `ops/devops/release/` and is invoked +by the new `.gitea/workflows/release.yml` pipeline. + +## Local dry run + +```bash +./ops/devops/release/build_release.py \ + --version 2025.10.0-edge \ + --channel edge \ + --dry-run +``` + +Outputs land under `out/release/`. Use `--no-push` to run full builds without +pushing to the registry. + +After the build completes, run the verifier to validate recorded hashes and artefact +presence: + +```bash +python ops/devops/release/verify_release.py --release-dir out/release +``` + +## Python analyzer smoke & signing + +`dotnet run --project src/Tools/LanguageAnalyzerSmoke` exercises the Python language +analyzer plug-in against the golden fixtures (cold/warm timings, determinism). The +release workflow runs this harness automatically and then produces Cosign +signatures + SHA-256 sidecars for `StellaOps.Scanner.Analyzers.Lang.Python.dll` +and its `manifest.json`. Keep `COSIGN_KEY_REF`/`COSIGN_IDENTITY_TOKEN` populated so +the step can sign the artefacts; the generated `.sig`/`.sha256` files ship with the +Offline Kit bundle. + +## Required tooling + +- Docker 25+ with Buildx +- .NET 10 preview SDK (builds container stages and the SBOM generator) +- Node.js 20 (Angular UI build) +- Helm 3.16+ +- Cosign 2.2+ + +Supply signing material via environment variables: + +- `COSIGN_KEY_REF` – e.g. `file:./keys/cosign.key` or `azurekms://…` +- `COSIGN_PASSWORD` – password protecting the above key + +The workflow defaults to multi-arch (`linux/amd64,linux/arm64`), SBOM in +CycloneDX, and SLSA provenance (`https://slsa.dev/provenance/v1`). + +## Debug store extraction + +`build_release.py` now exports stripped debug artefacts for every ELF discovered in the published images. The files land under `out/release/debug/.build-id//.debug`, with metadata captured in `debug/debug-manifest.json` (and a `.sha256` sidecar). Use `jq` to inspect the manifest or `readelf -n` to spot-check a build-id. Offline Kit packaging should reuse the `debug/` directory as-is. + +## UI auth smoke (Playwright) + +As part of **DEVOPS-UI-13-006** the pipelines will execute the UI auth smoke +tests (`npm run test:e2e`) after building the Angular bundle. See +`docs/modules/ui/operations/auth-smoke.md` for the job design, environment stubs, and +offline runner considerations. + +## NuGet preview bootstrap + +`.NET 10` preview packages (Microsoft.Extensions.*, JwtBearer 10.0 RC, Sqlite 9 RC) +ship from the public `dotnet-public` Azure DevOps feed. We mirror them into +`./local-nuget` so restores succeed inside Offline Kit. + +1. Run `./ops/devops/sync-preview-nuget.sh` whenever you update the manifest. +2. The script now understands the optional `SourceBase` column (V3 flat container) + and writes packages alongside their SHA-256 checks. +3. `NuGet.config` registers the mirror (`local`), dotnet-public, and nuget.org. + +Use `python3 ops/devops/validate_restore_sources.py` to prove the repo still +prefers the local mirror and that `Directory.Build.props` enforces the same order. +The validator now runs automatically in the `build-test-deploy` and `release` +workflows so CI fails fast when a feed priority regression slips in. + +Detailed operator instructions live in `docs/modules/devops/runbooks/nuget-preview-bootstrap.md`. + +## Telemetry collector tooling (DEVOPS-OBS-50-001) + +- `ops/devops/telemetry/generate_dev_tls.sh` – generates a development CA and + client/server certificates for the OpenTelemetry collector overlay (mutual TLS). +- `ops/devops/telemetry/smoke_otel_collector.py` – sends OTLP traces/metrics/logs + over TLS and validates that the collector increments its receiver counters. +- `ops/devops/telemetry/package_offline_bundle.py` – re-packages collector assets for the Offline Kit. +- `deploy/compose/docker-compose.telemetry-storage.yaml` – Prometheus/Tempo/Loki stack for staging validation. + +Combine these helpers with `deploy/compose/docker-compose.telemetry.yaml` to run +a secured collector locally before rolling out the Helm-based deployment. diff --git a/ops/devops/TASKS.md b/ops/devops/TASKS.md index 89a88fb5..3fb7bfd2 100644 --- a/ops/devops/TASKS.md +++ b/ops/devops/TASKS.md @@ -1,172 +1,172 @@ -# DevOps Task Board - -## Governance & Rules - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-RULES-33-001 | DOING (2025-10-26) | DevOps Guild, Platform Leads | — | Contracts & Rules anchor:
• Gateway proxies only; Policy Engine composes overlays/simulations.
• AOC ingestion cannot merge; only lossless canonicalization.
• One graph platform: Graph Indexer + Graph API. Cartographer retired. | Rules posted in SPRINTS/TASKS; duplicates cleaned per guidance; reviewers acknowledge in changelog. | - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-HELM-09-001 | DONE | DevOps Guild | SCANNER-WEB-09-101 | Create Helm/Compose environment profiles (dev, staging, airgap) with deterministic digests. | Profiles committed under `deploy/`; docs updated; CI smoke deploy passes. | -| DEVOPS-SCANNER-09-204 | DONE (2025-10-21) | DevOps Guild, Scanner WebService Guild | SCANNER-EVENTS-15-201 | Surface `SCANNER__EVENTS__*` environment variables across docker-compose (dev/stage/airgap) and Helm values, defaulting to share the Redis queue DSN. | Compose/Helm configs ship enabled Redis event publishing with documented overrides; lint jobs updated; docs cross-link to new knobs. | -| DEVOPS-SCANNER-09-205 | DONE (2025-10-21) | DevOps Guild, Notify Guild | DEVOPS-SCANNER-09-204 | Add Notify smoke stage that tails the Redis stream and asserts `scanner.report.ready`/`scanner.scan.completed` reach Notify WebService in staging. | CI job reads Redis stream during scanner smoke deploy, confirms Notify ingestion via API, alerts on failure. | -| DEVOPS-PERF-10-001 | DONE | DevOps Guild | BENCH-SCANNER-10-001 | Add perf smoke job (SBOM compose <5 s target) to CI. | CI job runs sample build verifying <5 s; alerts configured. | -| DEVOPS-PERF-10-002 | DONE (2025-10-23) | DevOps Guild | BENCH-SCANNER-10-002 | Publish analyzer bench metrics to Grafana/perf workbook and alarm on ≥20 % regressions. | CI exports JSON for dashboards; Grafana panel wired; Ops on-call doc updated with alert hook. | -| DEVOPS-AOC-19-001 | BLOCKED (2025-10-26) | DevOps Guild, Platform Guild | WEB-AOC-19-003 | Integrate the AOC Roslyn analyzer and guard tests into CI, failing builds when ingestion projects attempt banned writes. | Analyzer runs in PR/CI pipelines, results surfaced in build summary, docs updated under `docs/ops/ci-aoc.md`. | -> Docs hand-off (2025-10-26): see `docs/ingestion/aggregation-only-contract.md` §5, `docs/architecture/overview.md`, and `docs/cli/cli-reference.md` for guard + verifier expectations. -| DEVOPS-AOC-19-002 | BLOCKED (2025-10-26) | DevOps Guild | CLI-AOC-19-002, CONCELIER-WEB-AOC-19-004, EXCITITOR-WEB-AOC-19-004 | Add pipeline stage executing `stella aoc verify --since` against seeded Mongo snapshots for Concelier + Excititor, publishing violation report artefacts. | Stage runs on main/nightly, fails on violations, artifacts retained, runbook documented. | -> Blocked: waiting on CLI verifier command and Concelier/Excititor guard endpoints to land (CLI-AOC-19-002, CONCELIER-WEB-AOC-19-004, EXCITITOR-WEB-AOC-19-004). -| DEVOPS-AOC-19-003 | BLOCKED (2025-10-26) | DevOps Guild, QA Guild | CONCELIER-WEB-AOC-19-003, EXCITITOR-WEB-AOC-19-003 | Enforce unit test coverage thresholds for AOC guard suites and ensure coverage exported to dashboards. | Coverage report includes guard projects, threshold gate passes/fails as expected, dashboards refreshed with new metrics. | -> Blocked: guard coverage suites and exporter hooks pending in Concelier/Excititor (CONCELIER-WEB-AOC-19-003, EXCITITOR-WEB-AOC-19-003). -| DEVOPS-AOC-19-101 | TODO (2025-10-28) | DevOps Guild, Concelier Storage Guild | CONCELIER-STORE-AOC-19-002 | Draft supersedes backfill rollout (freeze window, dry-run steps, rollback) once advisory_raw idempotency index passes staging verification. | Runbook committed in `docs/deploy/containers.md` + Offline Kit notes, staging rehearsal scheduled with dependencies captured in SPRINTS. | -| DEVOPS-OBS-50-001 | DONE (2025-10-26) | DevOps Guild, Observability Guild | TELEMETRY-OBS-50-001 | Deliver default OpenTelemetry collector deployment (Compose/Helm manifests), OTLP ingestion endpoints, and secure pipeline (authN, mTLS, tenant partitioning). Provide smoke test verifying traces/logs/metrics ingestion. | Collector manifests committed; smoke test green; docs updated; imposed rule banner reminder noted. | -| DEVOPS-OBS-50-002 | DOING (2025-10-26) | DevOps Guild, Security Guild | DEVOPS-OBS-50-001, TELEMETRY-OBS-51-002 | Stand up multi-tenant storage backends (Prometheus, Tempo/Jaeger, Loki) with retention policies, tenant isolation, and redaction guard rails. Integrate with Authority scopes for read paths. | Storage stack deployed with auth; retention configured; integration tests verify tenant isolation; runbook drafted. | -> Coordination started with Observability Guild (2025-10-26) to schedule staging rollout and provision service accounts. Staging bootstrap commands and secret names documented in `docs/ops/telemetry-storage.md`. -| DEVOPS-OBS-50-003 | DONE (2025-10-26) | DevOps Guild, Offline Kit Guild | DEVOPS-OBS-50-001 | Package telemetry stack configs for air-gapped installs (Offline Kit bundle, documented overrides, sample values) and automate checksum/signature generation. | Offline bundle includes collector+storage configs; checksums published; docs cross-linked; imposed rule annotation recorded. | -| DEVOPS-OBS-51-001 | TODO | DevOps Guild, Observability Guild | WEB-OBS-51-001, DEVOPS-OBS-50-001 | Implement SLO evaluator service (burn rate calculators, webhook emitters), Grafana dashboards, and alert routing to Notifier. Provide Terraform/Helm automation. | Dashboards live; evaluator emits webhooks; alert runbook referenced; staging alert fired in test. | -| DEVOPS-OBS-52-001 | TODO | DevOps Guild, Timeline Indexer Guild | TIMELINE-OBS-52-002 | Configure streaming pipeline (NATS/Redis/Kafka) with retention, partitioning, and backpressure tuning for timeline events; add CI validation of schema + rate caps. | Pipeline deployed; load test meets SLA; schema validation job passes; documentation updated. | -| DEVOPS-OBS-53-001 | TODO | DevOps Guild, Evidence Locker Guild | EVID-OBS-53-001 | Provision object storage with WORM/retention options (S3 Object Lock / MinIO immutability), legal hold automation, and backup/restore scripts for evidence locker. | Storage configured with WORM; legal hold script documented; backup test performed; runbook updated. | -| DEVOPS-OBS-54-001 | TODO | DevOps Guild, Security Guild | PROV-OBS-53-002, EVID-OBS-54-001 | Manage provenance signing infrastructure (KMS keys, rotation schedule, timestamp authority integration) and integrate verification jobs into CI. | Keys provisioned with rotation policy; timestamp authority configured; CI verifies sample bundles; audit trail stored. | -| DEVOPS-OBS-55-001 | TODO | DevOps Guild, Ops Guild | DEVOPS-OBS-51-001, WEB-OBS-55-001 | Implement incident mode automation: feature flag service, auto-activation via SLO burn-rate, retention override management, and post-incident reset job. | Incident mode toggles via API/CLI; automation tested in staging; reset job verified; runbook referenced. | - -## Air-Gapped Mode (Epic 16) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-AIRGAP-56-001 | TODO | DevOps Guild | AIRGAP-CTL-56-001 | Ship deny-all egress policies for Kubernetes (NetworkPolicy/eBPF) and docker-compose firewall rules; provide verification script for sealed mode. | Policies committed with tests; verification script passes/fails as expected; docs cross-linked. | -| DEVOPS-AIRGAP-56-002 | TODO | DevOps Guild, AirGap Importer Guild | AIRGAP-IMP-57-002 | Provide import tooling for bundle staging: checksum validation, offline object-store loader scripts, removable media guidance. | Scripts documented; smoke tests validate import; runbook updated. | -| DEVOPS-AIRGAP-56-003 | TODO | DevOps Guild, Container Distribution Guild | EXPORT-AIRGAP-56-002 | Build Bootstrap Pack pipeline bundling images/charts, generating checksums, and publishing manifest for offline transfer. | Pipeline runs in connected env; pack verified in air-gap smoke test; manifest recorded. | -| DEVOPS-AIRGAP-57-001 | TODO | DevOps Guild, Mirror Creator Guild | MIRROR-CRT-56-002 | Automate Mirror Bundle creation jobs with dual-control approvals, artifact signing, and checksum publication. | Approval workflow enforced; CI artifact includes DSSE/TUF metadata; audit logs stored. | -| DEVOPS-AIRGAP-57-002 | TODO | DevOps Guild, Authority Guild | AUTH-OBS-50-001 | Configure sealed-mode CI tests that run services with sealed flag and ensure no egress occurs (iptables + mock DNS). | CI suite fails on attempted egress; reports remediation; documentation updated. | -| DEVOPS-AIRGAP-58-001 | TODO | DevOps Guild, Notifications Guild | NOTIFY-AIRGAP-56-002 | Provide local SMTP/syslog container templates and health checks for sealed environments; integrate into Bootstrap Pack. | Templates deployed successfully; health checks in CI; docs updated. | -| DEVOPS-AIRGAP-58-002 | TODO | DevOps Guild, Observability Guild | DEVOPS-AIRGAP-56-001, DEVOPS-OBS-51-001 | Ship sealed-mode observability stack (Prometheus/Grafana/Tempo/Loki) pre-configured with offline dashboards and no remote exporters. | Stack boots offline; dashboards available; verification script confirms zero egress. | -| DEVOPS-REL-14-001 | DONE (2025-10-26) | DevOps Guild | SIGNER-API-11-101, ATTESTOR-API-11-201 | Deterministic build/release pipeline with SBOM/provenance, signing, manifest generation. | CI pipeline produces signed images + SBOM/attestations, manifests published with verified hashes, docs updated. | -| DEVOPS-REL-14-004 | DONE (2025-10-26) | DevOps Guild, Scanner Guild | DEVOPS-REL-14-001, SCANNER-ANALYZERS-LANG-10-309P | Extend release/offline smoke jobs to exercise the Python analyzer plug-in (warm/cold scans, determinism, signature checks). | Release/Offline pipelines run Python analyzer smoke suite; alerts hooked; docs updated with new coverage matrix. | -| DEVOPS-REL-17-002 | DONE (2025-10-26) | DevOps Guild | DEVOPS-REL-14-001, SCANNER-EMIT-17-701 | Persist stripped-debug artifacts organised by GNU build-id and bundle them into release/offline kits with checksum manifests. | CI job writes `.debug` files under `artifacts/debug/.build-id/`, manifest + checksums published, offline kit includes cache, smoke job proves symbol lookup via build-id. | -| DEVOPS-REL-17-004 | BLOCKED (2025-10-26) | DevOps Guild | DEVOPS-REL-17-002 | Ensure release workflow publishes `out/release/debug` (build-id tree + manifest) and fails when symbols are missing. | Release job emits debug artefacts, `mirror_debug_store.py` summary committed, warning cleared from build logs, docs updated. | -| DEVOPS-MIRROR-08-001 | DONE (2025-10-19) | DevOps Guild | DEVOPS-REL-14-001 | Stand up managed mirror profiles for `*.stella-ops.org` (Concelier/Excititor), including Helm/Compose overlays, multi-tenant secrets, CDN caching, and sync documentation. | Infra overlays committed, CI smoke deploy hits mirror endpoints, runbooks published for downstream sync and quota management. | -> Note (2025-10-26, BLOCKED): IdentityModel.Tokens patched for logging 9.x, but release bundle still fails because Docker cannot stream multi-arch build context (`unix:///var/run/docker.sock` unavailable, EOF during copy). Retry once docker daemon/socket is healthy; until then `out/release/debug` cannot be generated. -| DEVOPS-CONSOLE-23-001 | BLOCKED (2025-10-26) | DevOps Guild, Console Guild | CONSOLE-CORE-23-001 | Add console CI workflow (pnpm cache, lint, type-check, unit, Storybook a11y, Playwright, Lighthouse) with offline runners and artifact retention for screenshots/reports. | Workflow runs on PR & main, caches reduce install time, failing checks block merges, artifacts uploaded for triage, docs updated. | -> Blocked: Console workspace and package scripts (CONSOLE-CORE-23-001..005) are not yet present; CI cannot execute pnpm/Playwright/Lighthouse until the Next.js app lands. -| DEVOPS-CONSOLE-23-002 | TODO | DevOps Guild, Console Guild | DEVOPS-CONSOLE-23-001, CONSOLE-REL-23-301 | Produce `stella-console` container build + Helm chart overlays with deterministic digests, SBOM/provenance artefacts, and offline bundle packaging scripts. | Container published to registry mirror, Helm values committed, SBOM/attestations generated, offline kit job passes smoke test, docs updated. | -| DEVOPS-LAUNCH-18-100 | DONE (2025-10-26) | DevOps Guild | - | Finalise production environment footprint (clusters, secrets, network overlays) for full-platform go-live. | IaC/compose overlays committed, secrets placeholders documented, dry-run deploy succeeds in staging. | -| DEVOPS-LAUNCH-18-900 | DONE (2025-10-26) | DevOps Guild, Module Leads | Wave 0 completion | Collect “full implementation” sign-off from module owners and consolidate launch readiness checklist. | Sign-off record stored under `docs/ops/launch-readiness.md`; outstanding gaps triaged; checklist approved. | -| DEVOPS-LAUNCH-18-001 | DONE (2025-10-26) | DevOps Guild | DEVOPS-LAUNCH-18-100, DEVOPS-LAUNCH-18-900 | Production launch cutover rehearsal and runbook publication. | `docs/ops/launch-cutover.md` drafted, rehearsal executed with rollback drill, approvals captured. | -| DEVOPS-NUGET-13-001 | DONE (2025-10-25) | DevOps Guild, Platform Leads | DEVOPS-REL-14-001 | Add .NET 10 preview feeds / local mirrors so `Microsoft.Extensions.*` 10.0 preview packages restore offline; refresh restore docs. | NuGet.config maps preview feeds (or local mirrored packages), `dotnet restore` succeeds for Excititor/Concelier solutions without ad-hoc feed edits, docs updated for offline bootstrap. | -| DEVOPS-NUGET-13-002 | DONE (2025-10-26) | DevOps Guild | DEVOPS-NUGET-13-001 | Ensure all solutions/projects prefer `local-nuget` before public sources and document restore order validation. | `NuGet.config` and solution-level configs resolve from `local-nuget` first; automated check verifies priority; docs updated for restore ordering. | -| DEVOPS-NUGET-13-003 | DONE (2025-10-26) | DevOps Guild, Platform Leads | DEVOPS-NUGET-13-002 | Sweep `Microsoft.*` NuGet dependencies pinned to 8.* and upgrade to latest .NET 10 equivalents (or .NET 9 when 10 unavailable), updating restore guidance. | Dependency audit shows no 8.* `Microsoft.*` packages remaining; CI builds green; changelog/doc sections capture upgrade rationale. | - -## Policy Engine v2 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-POLICY-20-001 | DONE (2025-10-26) | DevOps Guild, Policy Guild | POLICY-ENGINE-20-001 | Integrate DSL linting in CI (parser/compile) to block invalid policies; add pipeline step compiling sample policies. | CI fails on syntax errors; lint logs surfaced; docs updated with pipeline instructions. | -| DEVOPS-POLICY-20-003 | DONE (2025-10-26) | DevOps Guild, QA Guild | DEVOPS-POLICY-20-001, POLICY-ENGINE-20-005 | Determinism CI: run Policy Engine twice with identical inputs and diff outputs to guard non-determinism. | CI job compares outputs, fails on differences, logs stored; documentation updated. | -| DEVOPS-POLICY-20-004 | DONE (2025-10-27) | DevOps Guild, Scheduler Guild, CLI Guild | SCHED-MODELS-20-001, CLI-POLICY-20-002 | Automate policy schema exports: generate JSON Schema from `PolicyRun*` DTOs during CI, publish artefacts, and emit change alerts for CLI consumers (Slack + changelog). | CI stage outputs versioned schema files, uploads artefacts, notifies #policy-engine channel on change; docs/CLI references updated. | -> 2025-10-27: `.gitea/workflows/build-test-deploy.yml` publishes the `policy-schema-exports` artefact under `artifacts/policy-schemas//` and posts Slack diffs via `POLICY_ENGINE_SCHEMA_WEBHOOK`; diff stored as `policy-schema-diff.patch`. - -## Graph Explorer v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| - -## Orchestrator Dashboard - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-ORCH-32-001 | TODO | DevOps Guild, Orchestrator Service Guild | ORCH-SVC-32-001 | Provision orchestrator Postgres/message-bus infrastructure, add CI smoke deploy, seed Grafana dashboards (queue depth, inflight jobs), and document bootstrap. | Helm/Compose profiles committed; CI smoke deploy runs; dashboards live with metrics; runbook updated. | -| DEVOPS-ORCH-33-001 | TODO | DevOps Guild, Observability Guild | DEVOPS-ORCH-32-001, ORCH-SVC-33-001..003 | Publish Grafana dashboards/alerts for rate limiter, backpressure, error clustering, and DLQ depth; integrate with on-call rotations. | Dashboards and alerts configured; synthetic tests validate thresholds; on-call playbook updated. | -| DEVOPS-ORCH-34-001 | TODO | DevOps Guild, Orchestrator Service Guild | DEVOPS-ORCH-33-001, ORCH-SVC-34-001..003 | Harden production monitoring (synthetic probes, burn-rate alerts, replay smoke), document incident response, and prep GA readiness checklist. | Synthetic probes created; burn-rate alerts firing on test scenario; GA checklist approved; runbook linked. | - -## Link-Not-Merge v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-LNM-22-001 | BLOCKED (2025-10-27) | DevOps Guild, Concelier Guild | CONCELIER-LNM-21-102 | Run migration/backfill pipelines for advisory observations/linksets in staging, validate counts/conflicts, and automate deployment steps. Awaiting storage backfill tooling. | -| DEVOPS-LNM-22-002 | BLOCKED (2025-10-27) | DevOps Guild, Excititor Guild | EXCITITOR-LNM-21-102 | Execute VEX observation/linkset backfill with monitoring; ensure NATS/Redis events integrated; document ops runbook. Blocked until Excititor storage migration lands. | -| DEVOPS-LNM-22-003 | TODO | DevOps Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005 | Add CI/monitoring coverage for new metrics (`advisory_observations_total`, `linksets_total`, etc.) and alerts on ingest-to-API SLA breaches. | Metrics scraped into Grafana; alert thresholds set; CI job verifies metric emission. | - -## Graph & Vuln Explorer v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-GRAPH-24-001 | TODO | DevOps Guild, SBOM Service Guild | SBOM-GRAPH-24-002 | Load test graph index/adjacency APIs with 40k-node assets; capture perf dashboards and alert thresholds. | Perf suite added; dashboards live; alerts configured. | -| DEVOPS-GRAPH-24-002 | TODO | DevOps Guild, UI Guild | UI-GRAPH-24-001..005 | Integrate synthetic UI perf runs (Playwright/WebGL metrics) for Graph/Vuln explorers; fail builds on regression. | CI job runs UI perf tests; baseline stored; documentation updated. | -| DEVOPS-GRAPH-24-003 | TODO | DevOps Guild | WEB-GRAPH-24-002 | Implement smoke job for simulation endpoints ensuring we stay within SLA (<3s upgrade) and log results. | Smoke job in CI; alerts when SLA breached; runbook documented. | -| DEVOPS-POLICY-27-001 | TODO | DevOps Guild, DevEx/CLI Guild | CLI-POLICY-27-001, REGISTRY-API-27-001 | Add CI pipeline stages to run `stella policy lint|compile|test` with secret scanning on policy sources for PRs touching `/policies/**`; publish diagnostics artifacts. | Pipeline executes on PR/main, failures block merges, secret scan summary uploaded, docs updated. | -| DEVOPS-POLICY-27-002 | TODO | DevOps Guild, Policy Registry Guild | REGISTRY-API-27-005, SCHED-WORKER-27-301 | Provide optional batch simulation CI job (staging inventory) that triggers Registry run, polls results, and posts markdown summary to PR; enforce drift thresholds. | Job configurable via label, summary comment generated, drift threshold gates merges, runbook documented. | -| DEVOPS-POLICY-27-003 | TODO | DevOps Guild, Security Guild | AUTH-POLICY-27-002, REGISTRY-API-27-007 | Manage signing key material for policy publish pipeline (OIDC workload identity + cosign), rotate keys, and document verification steps; integrate attestation verification stage. | Keys stored in secure vault, rotation procedure documented, CI verifies attestations, audit logs recorded. | -| DEVOPS-POLICY-27-004 | TODO | DevOps Guild, Observability Guild | WEB-POLICY-27-005, TELEMETRY-CONSOLE-27-001 | Create dashboards/alerts for policy compile latency, simulation queue depth, approval latency, and promotion outcomes; integrate with on-call playbooks. | Grafana dashboards live, alerts tuned, runbooks updated, observability tests verify metric ingestion. | -> Remark (2025-10-20): Repacked `Mongo2Go` local feed to require MongoDB.Driver 3.5.0 + SharpCompress 0.41.0; cache regression tests green and NU1902/NU1903 suppressed. -> Remark (2025-10-21): Compose/Helm profiles now surface `SCANNER__EVENTS__*` toggles with docs pointing at new `.env` placeholders. - -## Reachability v1 - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-SIG-26-001 | TODO | DevOps Guild, Signals Guild | SIGNALS-24-001 | Provision CI/CD pipelines, Helm/Compose manifests for Signals service, including artifact storage and Redis dependencies. | Pipelines ship Signals service; deployment docs updated; smoke tests green. | -| DEVOPS-SIG-26-002 | TODO | DevOps Guild, Observability Guild | SIGNALS-24-004 | Create dashboards/alerts for reachability scoring latency, cache hit rates, sensor staleness. | Dashboards live; alert thresholds configured; documentation updated. | -| DEVOPS-VULN-29-001 | TODO | DevOps Guild, Findings Ledger Guild | LEDGER-29-002..009 | Provision CI jobs for ledger projector (replay, determinism), set up backups, monitor Merkle anchoring, and automate verification. | CI job verifies hash chains; backups documented; alerts for anchoring failures configured. | -| DEVOPS-VULN-29-002 | TODO | DevOps Guild, Vuln Explorer API Guild | VULN-API-29-002..009 | Configure load/perf tests (5M findings/tenant), query budget enforcement, API SLO dashboards, and alerts for `vuln_list_latency` and `projection_lag`. | Perf suite integrated; dashboards live; alerts firing; runbooks updated. | -| DEVOPS-VULN-29-003 | TODO | DevOps Guild, Console Guild | WEB-VULN-29-004, CONSOLE-VULN-29-007 | Instrument analytics pipeline for Vuln Explorer (telemetry ingestion, query hashes), ensure compliance with privacy/PII guardrails, and update observability docs. | Telemetry pipeline operational; PII redaction verified; docs updated with checklist. | -| DEVOPS-VEX-30-001 | TODO | DevOps Guild, VEX Lens Guild | VEXLENS-30-009, ISSUER-30-005 | Provision CI, load tests, dashboards, alerts for VEX Lens and Issuer Directory (compute latency, disputed totals, signature verification rates). | CI/perf suites running; dashboards live; alerts configured; docs updated. | -| DEVOPS-AIAI-31-001 | TODO | DevOps Guild, Advisory AI Guild | AIAI-31-006..007 | Stand up CI pipelines, inference monitoring, privacy logging review, and perf dashboards for Advisory AI (summaries/conflicts/remediation). | CI covers golden outputs, telemetry dashboards live, privacy controls reviewed, alerts configured. | - -## Export Center -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-EXPORT-35-001 | BLOCKED (2025-10-29) | DevOps Guild, Exporter Service Guild | EXPORT-SVC-35-001..006 | Establish exporter CI pipeline (lint/test/perf smoke), configure object storage fixtures, seed Grafana dashboards, and document bootstrap steps. | CI pipeline running; smoke export job seeded; dashboards live; runbook updated. | -| DEVOPS-EXPORT-36-001 | TODO | DevOps Guild, Exporter Service Guild | DEVOPS-EXPORT-35-001, EXPORT-SVC-36-001..004 | Integrate Trivy compatibility validation, cosign signature checks, `trivy module db import` smoke tests, OCI distribution verification, and throughput/error dashboards. | CI executes cosign + Trivy import validation; OCI push smoke passes; dashboards/alerts configured. | -| DEVOPS-EXPORT-37-001 | TODO | DevOps Guild, Exporter Service Guild | DEVOPS-EXPORT-36-001, EXPORT-SVC-37-001..004 | Finalize exporter monitoring (failure alerts, verify metrics, retention jobs) and chaos/latency tests ahead of GA. | Alerts tuned; chaos tests documented; retention monitoring active; runbook updated. | - -## CLI Parity & Task Packs - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-CLI-41-001 | TODO | DevOps Guild, DevEx/CLI Guild | CLI-CORE-41-001 | Establish CLI build pipeline (multi-platform binaries, SBOM, checksums), parity matrix CI enforcement, and release artifact signing. | Build pipeline operational; SBOM/checksums published; parity gate failing on drift; docs updated. | -| DEVOPS-CLI-42-001 | TODO | DevOps Guild | DEVOPS-CLI-41-001, CLI-PARITY-41-001 | Add CLI golden output tests, parity diff automation, pack run CI harness, and artifact cache for remote mode. | Golden tests running; parity diff automation in CI; pack run harness executes sample packs; documentation updated. | -| DEVOPS-CLI-43-001 | DOING (2025-10-27) | DevOps Guild | DEVOPS-CLI-42-001, TASKRUN-42-001 | Finalize multi-platform release automation, SBOM signing, parity gate enforcement, and Task Pack chaos tests. | Release automation verified; SBOM signed; parity gate enforced; chaos tests documented. | -> 2025-10-27: Release pipeline now packages CLI multi-platform artefacts with SBOM/signature coverage and enforces the CLI parity gate (`ops/devops/check_cli_parity.py`). Task Pack chaos smoke still pending CLI pack command delivery. -| DEVOPS-CLI-43-002 | TODO | DevOps Guild, Task Runner Guild | CLI-PACKS-43-001, TASKRUN-43-001 | Implement Task Pack chaos smoke in CI (random failure injection, resume, sealed-mode toggle) and publish evidence bundles for review. | Chaos smoke job runs nightly; failures alert Slack; evidence stored in `out/pack-chaos`; runbook updated. | -| DEVOPS-CLI-43-003 | TODO | DevOps Guild, DevEx/CLI Guild | CLI-PARITY-41-001, CLI-PACKS-42-001 | Integrate CLI golden output/parity diff automation into release gating; export parity report artifact consumed by Console Downloads workspace. | `check_cli_parity.py` wired to compare parity matrix and CLI outputs; artifact uploaded; release fails on regressions. - -## Containerized Distribution (Epic 13) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-CONTAINERS-44-001 | TODO | DevOps Guild | DOCKER-44-001..003 | Automate multi-arch image builds with buildx, SBOM generation, cosign signing, and signature verification in CI. | Pipeline builds amd64/arm64; SBOMs pushed as referrers; cosign verify job passes. | -| DEVOPS-CONTAINERS-45-001 | TODO | DevOps Guild | HELM-45-001 | Add Compose and Helm smoke tests (fresh VM + kind cluster) to CI; publish test artifacts and logs. | CI jobs running; failures block releases; documentation updated. | -| DEVOPS-CONTAINERS-46-001 | TODO | DevOps Guild | DEPLOY-PACKS-43-001 | Build air-gap bundle generator (`tools/make-airgap-bundle.sh`), produce signed bundle, and verify in CI using private registry. | Bundle artifact produced with signatures/checksums; verification job passes; instructions documented. | - -### Container Images (Epic 13) - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DOCKER-44-001 | TODO | DevOps Guild, Service Owners | DEVOPS-CLI-41-001 | Author multi-stage Dockerfiles for all core services (API, Console, Orchestrator, Task Runner, Conseiller, Excitator, Policy, Notify, Export, AI) with non-root users, read-only file systems, and health scripts. | Dockerfiles committed; images build successfully; container security scans clean; health endpoints reachable. | -| DOCKER-44-002 | TODO | DevOps Guild | DOCKER-44-001 | Generate SBOMs and cosign attestations for each image and integrate verification into CI. | SBOMs attached as OCI artifacts; cosign signatures published; CI verifies signatures prior to release. | -| DOCKER-44-003 | TODO | DevOps Guild | DOCKER-44-001 | Implement `/health/liveness`, `/health/readiness`, `/version`, `/metrics`, and ensure capability endpoint returns `merge=false` for Conseiller/Excitator. | Endpoints available across services; automated tests confirm responses; documentation updated with imposed rule reminder. | - -## Authority-Backed Scopes & Tenancy (Epic 14) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-TEN-47-001 | TODO | DevOps Guild | AUTH-TEN-47-001 | Add JWKS cache monitoring, signature verification regression tests, and token expiration chaos tests to CI. | CI verifies tokens using cached keys; chaos test for expired keys passes; documentation updated. | -| DEVOPS-TEN-48-001 | TODO | DevOps Guild | WEB-TEN-48-001 | Build integration tests to assert RLS enforcement, tenant-prefixed object storage, and audit event emission; set up lint to prevent raw SQL bypass. | Tests fail on cross-tenant access; lint enforced; dashboards capture audit events. | -| DEVOPS-TEN-49-001 | TODO | DevOps Guild | AUTH-TEN-49-001 | Deploy audit pipeline, scope usage metrics, JWKS outage chaos tests, and tenant load/perf benchmarks. | Audit pipeline live; metrics dashboards updated; chaos tests documented; perf benchmarks recorded. | - -## SDKs & OpenAPI (Epic 17) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-OAS-61-001 | TODO | DevOps Guild, API Contracts Guild | OAS-61-002 | Add CI stages for OpenAPI linting, validation, and compatibility diff; enforce gating on PRs. | Pipeline active; merge blocked on failures; documentation updated. | -| DEVOPS-OAS-61-002 | TODO | DevOps Guild, Contract Testing Guild | CONTR-62-002 | Integrate mock server + contract test suite into PR and nightly workflows; publish artifacts. | Tests run in CI; artifacts stored; failures alert. | -| DEVOPS-SDK-63-001 | TODO | DevOps Guild, SDK Release Guild | SDKREL-63-001 | Provision registry credentials, signing keys, and secure storage for SDK publishing pipelines. | Keys stored/rotated; publish pipeline authenticated; audit logs recorded. | -| DEVOPS-DEVPORT-63-001 | TODO | DevOps Guild, Developer Portal Guild | DEVPORT-62-001 | Automate developer portal build pipeline with caching, link & accessibility checks, performance budgets. | Pipeline enforced; reports archived; failures gate merges. | -| DEVOPS-DEVPORT-64-001 | TODO | DevOps Guild, DevPortal Offline Guild | DVOFF-64-001 | Schedule `devportal --offline` nightly builds with checksum validation and artifact retention policies. | Nightly job running; checksums published; retention policy documented. | - -## Attestor Console (Epic 19) -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| DEVOPS-ATTEST-73-001 | TODO | DevOps Guild, Attestor Service Guild | ATTESTOR-72-002 | Provision CI pipelines for attestor service (lint/test/security scan, seed data) and manage secrets for KMS drivers. | CI pipeline running; secrets stored securely; docs updated. | -| DEVOPS-ATTEST-73-002 | TODO | DevOps Guild, KMS Guild | KMS-72-001 | Establish secure storage for signing keys (vault integration, rotation schedule) and audit logging. | Key storage configured; rotation documented; audit logs verified. | -| DEVOPS-ATTEST-74-001 | TODO | DevOps Guild, Transparency Guild | TRANSP-74-001 | Deploy transparency log witness infrastructure and monitoring. | Witness service deployed; dashboards/alerts live. | -| DEVOPS-ATTEST-74-002 | TODO | DevOps Guild, Export Attestation Guild | EXPORT-ATTEST-74-001 | Integrate attestation bundle builds into release/offline pipelines with checksum verification. | Bundle job in CI; checksum verification passes; docs updated. | -| DEVOPS-ATTEST-75-001 | TODO | DevOps Guild, Observability Guild | ATTEST-VERIFY-74-001 | Add dashboards/alerts for signing latency, verification failures, key rotation events. | Dashboards live; alerts configured. | +# DevOps Task Board + +## Governance & Rules + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-RULES-33-001 | DOING (2025-10-26) | DevOps Guild, Platform Leads | — | Contracts & Rules anchor:
• Gateway proxies only; Policy Engine composes overlays/simulations.
• AOC ingestion cannot merge; only lossless canonicalization.
• One graph platform: Graph Indexer + Graph API. Cartographer retired. | Rules posted in SPRINTS/TASKS; duplicates cleaned per guidance; reviewers acknowledge in changelog. | + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-HELM-09-001 | DONE | DevOps Guild | SCANNER-WEB-09-101 | Create Helm/Compose environment profiles (dev, staging, airgap) with deterministic digests. | Profiles committed under `deploy/`; docs updated; CI smoke deploy passes. | +| DEVOPS-SCANNER-09-204 | DONE (2025-10-21) | DevOps Guild, Scanner WebService Guild | SCANNER-EVENTS-15-201 | Surface `SCANNER__EVENTS__*` environment variables across docker-compose (dev/stage/airgap) and Helm values, defaulting to share the Redis queue DSN. | Compose/Helm configs ship enabled Redis event publishing with documented overrides; lint jobs updated; docs cross-link to new knobs. | +| DEVOPS-SCANNER-09-205 | DONE (2025-10-21) | DevOps Guild, Notify Guild | DEVOPS-SCANNER-09-204 | Add Notify smoke stage that tails the Redis stream and asserts `scanner.report.ready`/`scanner.scan.completed` reach Notify WebService in staging. | CI job reads Redis stream during scanner smoke deploy, confirms Notify ingestion via API, alerts on failure. | +| DEVOPS-PERF-10-001 | DONE | DevOps Guild | BENCH-SCANNER-10-001 | Add perf smoke job (SBOM compose <5 s target) to CI. | CI job runs sample build verifying <5 s; alerts configured. | +| DEVOPS-PERF-10-002 | DONE (2025-10-23) | DevOps Guild | BENCH-SCANNER-10-002 | Publish analyzer bench metrics to Grafana/perf workbook and alarm on ≥20 % regressions. | CI exports JSON for dashboards; Grafana panel wired; Ops on-call doc updated with alert hook. | +| DEVOPS-AOC-19-001 | BLOCKED (2025-10-26) | DevOps Guild, Platform Guild | WEB-AOC-19-003 | Integrate the AOC Roslyn analyzer and guard tests into CI, failing builds when ingestion projects attempt banned writes. | Analyzer runs in PR/CI pipelines, results surfaced in build summary, docs updated under `docs/modules/devops/runbooks/ci-aoc.md`. | +> Docs hand-off (2025-10-26): see `docs/ingestion/aggregation-only-contract.md` §5, `docs/modules/platform/architecture-overview.md`, and `docs/modules/cli/guides/cli-reference.md` for guard + verifier expectations. +| DEVOPS-AOC-19-002 | BLOCKED (2025-10-26) | DevOps Guild | CLI-AOC-19-002, CONCELIER-WEB-AOC-19-004, EXCITITOR-WEB-AOC-19-004 | Add pipeline stage executing `stella aoc verify --since` against seeded Mongo snapshots for Concelier + Excititor, publishing violation report artefacts. | Stage runs on main/nightly, fails on violations, artifacts retained, runbook documented. | +> Blocked: waiting on CLI verifier command and Concelier/Excititor guard endpoints to land (CLI-AOC-19-002, CONCELIER-WEB-AOC-19-004, EXCITITOR-WEB-AOC-19-004). +| DEVOPS-AOC-19-003 | BLOCKED (2025-10-26) | DevOps Guild, QA Guild | CONCELIER-WEB-AOC-19-003, EXCITITOR-WEB-AOC-19-003 | Enforce unit test coverage thresholds for AOC guard suites and ensure coverage exported to dashboards. | Coverage report includes guard projects, threshold gate passes/fails as expected, dashboards refreshed with new metrics. | +> Blocked: guard coverage suites and exporter hooks pending in Concelier/Excititor (CONCELIER-WEB-AOC-19-003, EXCITITOR-WEB-AOC-19-003). +| DEVOPS-AOC-19-101 | TODO (2025-10-28) | DevOps Guild, Concelier Storage Guild | CONCELIER-STORE-AOC-19-002 | Draft supersedes backfill rollout (freeze window, dry-run steps, rollback) once advisory_raw idempotency index passes staging verification. | Runbook committed in `docs/deploy/containers.md` + Offline Kit notes, staging rehearsal scheduled with dependencies captured in SPRINTS. | +| DEVOPS-OBS-50-001 | DONE (2025-10-26) | DevOps Guild, Observability Guild | TELEMETRY-OBS-50-001 | Deliver default OpenTelemetry collector deployment (Compose/Helm manifests), OTLP ingestion endpoints, and secure pipeline (authN, mTLS, tenant partitioning). Provide smoke test verifying traces/logs/metrics ingestion. | Collector manifests committed; smoke test green; docs updated; imposed rule banner reminder noted. | +| DEVOPS-OBS-50-002 | DOING (2025-10-26) | DevOps Guild, Security Guild | DEVOPS-OBS-50-001, TELEMETRY-OBS-51-002 | Stand up multi-tenant storage backends (Prometheus, Tempo/Jaeger, Loki) with retention policies, tenant isolation, and redaction guard rails. Integrate with Authority scopes for read paths. | Storage stack deployed with auth; retention configured; integration tests verify tenant isolation; runbook drafted. | +> Coordination started with Observability Guild (2025-10-26) to schedule staging rollout and provision service accounts. Staging bootstrap commands and secret names documented in `docs/modules/telemetry/operations/storage.md`. +| DEVOPS-OBS-50-003 | DONE (2025-10-26) | DevOps Guild, Offline Kit Guild | DEVOPS-OBS-50-001 | Package telemetry stack configs for air-gapped installs (Offline Kit bundle, documented overrides, sample values) and automate checksum/signature generation. | Offline bundle includes collector+storage configs; checksums published; docs cross-linked; imposed rule annotation recorded. | +| DEVOPS-OBS-51-001 | TODO | DevOps Guild, Observability Guild | WEB-OBS-51-001, DEVOPS-OBS-50-001 | Implement SLO evaluator service (burn rate calculators, webhook emitters), Grafana dashboards, and alert routing to Notifier. Provide Terraform/Helm automation. | Dashboards live; evaluator emits webhooks; alert runbook referenced; staging alert fired in test. | +| DEVOPS-OBS-52-001 | TODO | DevOps Guild, Timeline Indexer Guild | TIMELINE-OBS-52-002 | Configure streaming pipeline (NATS/Redis/Kafka) with retention, partitioning, and backpressure tuning for timeline events; add CI validation of schema + rate caps. | Pipeline deployed; load test meets SLA; schema validation job passes; documentation updated. | +| DEVOPS-OBS-53-001 | TODO | DevOps Guild, Evidence Locker Guild | EVID-OBS-53-001 | Provision object storage with WORM/retention options (S3 Object Lock / MinIO immutability), legal hold automation, and backup/restore scripts for evidence locker. | Storage configured with WORM; legal hold script documented; backup test performed; runbook updated. | +| DEVOPS-OBS-54-001 | TODO | DevOps Guild, Security Guild | PROV-OBS-53-002, EVID-OBS-54-001 | Manage provenance signing infrastructure (KMS keys, rotation schedule, timestamp authority integration) and integrate verification jobs into CI. | Keys provisioned with rotation policy; timestamp authority configured; CI verifies sample bundles; audit trail stored. | +| DEVOPS-OBS-55-001 | TODO | DevOps Guild, Ops Guild | DEVOPS-OBS-51-001, WEB-OBS-55-001 | Implement incident mode automation: feature flag service, auto-activation via SLO burn-rate, retention override management, and post-incident reset job. | Incident mode toggles via API/CLI; automation tested in staging; reset job verified; runbook referenced. | + +## Air-Gapped Mode (Epic 16) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-AIRGAP-56-001 | TODO | DevOps Guild | AIRGAP-CTL-56-001 | Ship deny-all egress policies for Kubernetes (NetworkPolicy/eBPF) and docker-compose firewall rules; provide verification script for sealed mode. | Policies committed with tests; verification script passes/fails as expected; docs cross-linked. | +| DEVOPS-AIRGAP-56-002 | TODO | DevOps Guild, AirGap Importer Guild | AIRGAP-IMP-57-002 | Provide import tooling for bundle staging: checksum validation, offline object-store loader scripts, removable media guidance. | Scripts documented; smoke tests validate import; runbook updated. | +| DEVOPS-AIRGAP-56-003 | TODO | DevOps Guild, Container Distribution Guild | EXPORT-AIRGAP-56-002 | Build Bootstrap Pack pipeline bundling images/charts, generating checksums, and publishing manifest for offline transfer. | Pipeline runs in connected env; pack verified in air-gap smoke test; manifest recorded. | +| DEVOPS-AIRGAP-57-001 | TODO | DevOps Guild, Mirror Creator Guild | MIRROR-CRT-56-002 | Automate Mirror Bundle creation jobs with dual-control approvals, artifact signing, and checksum publication. | Approval workflow enforced; CI artifact includes DSSE/TUF metadata; audit logs stored. | +| DEVOPS-AIRGAP-57-002 | TODO | DevOps Guild, Authority Guild | AUTH-OBS-50-001 | Configure sealed-mode CI tests that run services with sealed flag and ensure no egress occurs (iptables + mock DNS). | CI suite fails on attempted egress; reports remediation; documentation updated. | +| DEVOPS-AIRGAP-58-001 | TODO | DevOps Guild, Notifications Guild | NOTIFY-AIRGAP-56-002 | Provide local SMTP/syslog container templates and health checks for sealed environments; integrate into Bootstrap Pack. | Templates deployed successfully; health checks in CI; docs updated. | +| DEVOPS-AIRGAP-58-002 | TODO | DevOps Guild, Observability Guild | DEVOPS-AIRGAP-56-001, DEVOPS-OBS-51-001 | Ship sealed-mode observability stack (Prometheus/Grafana/Tempo/Loki) pre-configured with offline dashboards and no remote exporters. | Stack boots offline; dashboards available; verification script confirms zero egress. | +| DEVOPS-REL-14-001 | DONE (2025-10-26) | DevOps Guild | SIGNER-API-11-101, ATTESTOR-API-11-201 | Deterministic build/release pipeline with SBOM/provenance, signing, manifest generation. | CI pipeline produces signed images + SBOM/attestations, manifests published with verified hashes, docs updated. | +| DEVOPS-REL-14-004 | DONE (2025-10-26) | DevOps Guild, Scanner Guild | DEVOPS-REL-14-001, SCANNER-ANALYZERS-LANG-10-309P | Extend release/offline smoke jobs to exercise the Python analyzer plug-in (warm/cold scans, determinism, signature checks). | Release/Offline pipelines run Python analyzer smoke suite; alerts hooked; docs updated with new coverage matrix. | +| DEVOPS-REL-17-002 | DONE (2025-10-26) | DevOps Guild | DEVOPS-REL-14-001, SCANNER-EMIT-17-701 | Persist stripped-debug artifacts organised by GNU build-id and bundle them into release/offline kits with checksum manifests. | CI job writes `.debug` files under `artifacts/debug/.build-id/`, manifest + checksums published, offline kit includes cache, smoke job proves symbol lookup via build-id. | +| DEVOPS-REL-17-004 | BLOCKED (2025-10-26) | DevOps Guild | DEVOPS-REL-17-002 | Ensure release workflow publishes `out/release/debug` (build-id tree + manifest) and fails when symbols are missing. | Release job emits debug artefacts, `mirror_debug_store.py` summary committed, warning cleared from build logs, docs updated. | +| DEVOPS-MIRROR-08-001 | DONE (2025-10-19) | DevOps Guild | DEVOPS-REL-14-001 | Stand up managed mirror profiles for `*.stella-ops.org` (Concelier/Excititor), including Helm/Compose overlays, multi-tenant secrets, CDN caching, and sync documentation. | Infra overlays committed, CI smoke deploy hits mirror endpoints, runbooks published for downstream sync and quota management. | +> Note (2025-10-26, BLOCKED): IdentityModel.Tokens patched for logging 9.x, but release bundle still fails because Docker cannot stream multi-arch build context (`unix:///var/run/docker.sock` unavailable, EOF during copy). Retry once docker daemon/socket is healthy; until then `out/release/debug` cannot be generated. +| DEVOPS-CONSOLE-23-001 | BLOCKED (2025-10-26) | DevOps Guild, Console Guild | CONSOLE-CORE-23-001 | Add console CI workflow (pnpm cache, lint, type-check, unit, Storybook a11y, Playwright, Lighthouse) with offline runners and artifact retention for screenshots/reports. | Workflow runs on PR & main, caches reduce install time, failing checks block merges, artifacts uploaded for triage, docs updated. | +> Blocked: Console workspace and package scripts (CONSOLE-CORE-23-001..005) are not yet present; CI cannot execute pnpm/Playwright/Lighthouse until the Next.js app lands. +| DEVOPS-CONSOLE-23-002 | TODO | DevOps Guild, Console Guild | DEVOPS-CONSOLE-23-001, CONSOLE-REL-23-301 | Produce `stella-console` container build + Helm chart overlays with deterministic digests, SBOM/provenance artefacts, and offline bundle packaging scripts. | Container published to registry mirror, Helm values committed, SBOM/attestations generated, offline kit job passes smoke test, docs updated. | +| DEVOPS-LAUNCH-18-100 | DONE (2025-10-26) | DevOps Guild | - | Finalise production environment footprint (clusters, secrets, network overlays) for full-platform go-live. | IaC/compose overlays committed, secrets placeholders documented, dry-run deploy succeeds in staging. | +| DEVOPS-LAUNCH-18-900 | DONE (2025-10-26) | DevOps Guild, Module Leads | Wave 0 completion | Collect “full implementation” sign-off from module owners and consolidate launch readiness checklist. | Sign-off record stored under `docs/modules/devops/runbooks/launch-readiness.md`; outstanding gaps triaged; checklist approved. | +| DEVOPS-LAUNCH-18-001 | DONE (2025-10-26) | DevOps Guild | DEVOPS-LAUNCH-18-100, DEVOPS-LAUNCH-18-900 | Production launch cutover rehearsal and runbook publication. | `docs/modules/devops/runbooks/launch-cutover.md` drafted, rehearsal executed with rollback drill, approvals captured. | +| DEVOPS-NUGET-13-001 | DONE (2025-10-25) | DevOps Guild, Platform Leads | DEVOPS-REL-14-001 | Add .NET 10 preview feeds / local mirrors so `Microsoft.Extensions.*` 10.0 preview packages restore offline; refresh restore docs. | NuGet.config maps preview feeds (or local mirrored packages), `dotnet restore` succeeds for Excititor/Concelier solutions without ad-hoc feed edits, docs updated for offline bootstrap. | +| DEVOPS-NUGET-13-002 | DONE (2025-10-26) | DevOps Guild | DEVOPS-NUGET-13-001 | Ensure all solutions/projects prefer `local-nuget` before public sources and document restore order validation. | `NuGet.config` and solution-level configs resolve from `local-nuget` first; automated check verifies priority; docs updated for restore ordering. | +| DEVOPS-NUGET-13-003 | DONE (2025-10-26) | DevOps Guild, Platform Leads | DEVOPS-NUGET-13-002 | Sweep `Microsoft.*` NuGet dependencies pinned to 8.* and upgrade to latest .NET 10 equivalents (or .NET 9 when 10 unavailable), updating restore guidance. | Dependency audit shows no 8.* `Microsoft.*` packages remaining; CI builds green; changelog/doc sections capture upgrade rationale. | + +## Policy Engine v2 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-POLICY-20-001 | DONE (2025-10-26) | DevOps Guild, Policy Guild | POLICY-ENGINE-20-001 | Integrate DSL linting in CI (parser/compile) to block invalid policies; add pipeline step compiling sample policies. | CI fails on syntax errors; lint logs surfaced; docs updated with pipeline instructions. | +| DEVOPS-POLICY-20-003 | DONE (2025-10-26) | DevOps Guild, QA Guild | DEVOPS-POLICY-20-001, POLICY-ENGINE-20-005 | Determinism CI: run Policy Engine twice with identical inputs and diff outputs to guard non-determinism. | CI job compares outputs, fails on differences, logs stored; documentation updated. | +| DEVOPS-POLICY-20-004 | DONE (2025-10-27) | DevOps Guild, Scheduler Guild, CLI Guild | SCHED-MODELS-20-001, CLI-POLICY-20-002 | Automate policy schema exports: generate JSON Schema from `PolicyRun*` DTOs during CI, publish artefacts, and emit change alerts for CLI consumers (Slack + changelog). | CI stage outputs versioned schema files, uploads artefacts, notifies #policy-engine channel on change; docs/CLI references updated. | +> 2025-10-27: `.gitea/workflows/build-test-deploy.yml` publishes the `policy-schema-exports` artefact under `artifacts/policy-schemas//` and posts Slack diffs via `POLICY_ENGINE_SCHEMA_WEBHOOK`; diff stored as `policy-schema-diff.patch`. + +## Graph Explorer v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| + +## Orchestrator Dashboard + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-ORCH-32-001 | TODO | DevOps Guild, Orchestrator Service Guild | ORCH-SVC-32-001 | Provision orchestrator Postgres/message-bus infrastructure, add CI smoke deploy, seed Grafana dashboards (queue depth, inflight jobs), and document bootstrap. | Helm/Compose profiles committed; CI smoke deploy runs; dashboards live with metrics; runbook updated. | +| DEVOPS-ORCH-33-001 | TODO | DevOps Guild, Observability Guild | DEVOPS-ORCH-32-001, ORCH-SVC-33-001..003 | Publish Grafana dashboards/alerts for rate limiter, backpressure, error clustering, and DLQ depth; integrate with on-call rotations. | Dashboards and alerts configured; synthetic tests validate thresholds; on-call playbook updated. | +| DEVOPS-ORCH-34-001 | TODO | DevOps Guild, Orchestrator Service Guild | DEVOPS-ORCH-33-001, ORCH-SVC-34-001..003 | Harden production monitoring (synthetic probes, burn-rate alerts, replay smoke), document incident response, and prep GA readiness checklist. | Synthetic probes created; burn-rate alerts firing on test scenario; GA checklist approved; runbook linked. | + +## Link-Not-Merge v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-LNM-22-001 | BLOCKED (2025-10-27) | DevOps Guild, Concelier Guild | CONCELIER-LNM-21-102 | Run migration/backfill pipelines for advisory observations/linksets in staging, validate counts/conflicts, and automate deployment steps. Awaiting storage backfill tooling. | +| DEVOPS-LNM-22-002 | BLOCKED (2025-10-27) | DevOps Guild, Excititor Guild | EXCITITOR-LNM-21-102 | Execute VEX observation/linkset backfill with monitoring; ensure NATS/Redis events integrated; document ops runbook. Blocked until Excititor storage migration lands. | +| DEVOPS-LNM-22-003 | TODO | DevOps Guild, Observability Guild | CONCELIER-LNM-21-005, EXCITITOR-LNM-21-005 | Add CI/monitoring coverage for new metrics (`advisory_observations_total`, `linksets_total`, etc.) and alerts on ingest-to-API SLA breaches. | Metrics scraped into Grafana; alert thresholds set; CI job verifies metric emission. | + +## Graph & Vuln Explorer v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-GRAPH-24-001 | TODO | DevOps Guild, SBOM Service Guild | SBOM-GRAPH-24-002 | Load test graph index/adjacency APIs with 40k-node assets; capture perf dashboards and alert thresholds. | Perf suite added; dashboards live; alerts configured. | +| DEVOPS-GRAPH-24-002 | TODO | DevOps Guild, UI Guild | UI-GRAPH-24-001..005 | Integrate synthetic UI perf runs (Playwright/WebGL metrics) for Graph/Vuln explorers; fail builds on regression. | CI job runs UI perf tests; baseline stored; documentation updated. | +| DEVOPS-GRAPH-24-003 | TODO | DevOps Guild | WEB-GRAPH-24-002 | Implement smoke job for simulation endpoints ensuring we stay within SLA (<3s upgrade) and log results. | Smoke job in CI; alerts when SLA breached; runbook documented. | +| DEVOPS-POLICY-27-001 | TODO | DevOps Guild, DevEx/CLI Guild | CLI-POLICY-27-001, REGISTRY-API-27-001 | Add CI pipeline stages to run `stella policy lint|compile|test` with secret scanning on policy sources for PRs touching `/policies/**`; publish diagnostics artifacts. | Pipeline executes on PR/main, failures block merges, secret scan summary uploaded, docs updated. | +| DEVOPS-POLICY-27-002 | TODO | DevOps Guild, Policy Registry Guild | REGISTRY-API-27-005, SCHED-WORKER-27-301 | Provide optional batch simulation CI job (staging inventory) that triggers Registry run, polls results, and posts markdown summary to PR; enforce drift thresholds. | Job configurable via label, summary comment generated, drift threshold gates merges, runbook documented. | +| DEVOPS-POLICY-27-003 | TODO | DevOps Guild, Security Guild | AUTH-POLICY-27-002, REGISTRY-API-27-007 | Manage signing key material for policy publish pipeline (OIDC workload identity + cosign), rotate keys, and document verification steps; integrate attestation verification stage. | Keys stored in secure vault, rotation procedure documented, CI verifies attestations, audit logs recorded. | +| DEVOPS-POLICY-27-004 | TODO | DevOps Guild, Observability Guild | WEB-POLICY-27-005, TELEMETRY-CONSOLE-27-001 | Create dashboards/alerts for policy compile latency, simulation queue depth, approval latency, and promotion outcomes; integrate with on-call playbooks. | Grafana dashboards live, alerts tuned, runbooks updated, observability tests verify metric ingestion. | +> Remark (2025-10-20): Repacked `Mongo2Go` local feed to require MongoDB.Driver 3.5.0 + SharpCompress 0.41.0; cache regression tests green and NU1902/NU1903 suppressed. +> Remark (2025-10-21): Compose/Helm profiles now surface `SCANNER__EVENTS__*` toggles with docs pointing at new `.env` placeholders. + +## Reachability v1 + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-SIG-26-001 | TODO | DevOps Guild, Signals Guild | SIGNALS-24-001 | Provision CI/CD pipelines, Helm/Compose manifests for Signals service, including artifact storage and Redis dependencies. | Pipelines ship Signals service; deployment docs updated; smoke tests green. | +| DEVOPS-SIG-26-002 | TODO | DevOps Guild, Observability Guild | SIGNALS-24-004 | Create dashboards/alerts for reachability scoring latency, cache hit rates, sensor staleness. | Dashboards live; alert thresholds configured; documentation updated. | +| DEVOPS-VULN-29-001 | TODO | DevOps Guild, Findings Ledger Guild | LEDGER-29-002..009 | Provision CI jobs for ledger projector (replay, determinism), set up backups, monitor Merkle anchoring, and automate verification. | CI job verifies hash chains; backups documented; alerts for anchoring failures configured. | +| DEVOPS-VULN-29-002 | TODO | DevOps Guild, Vuln Explorer API Guild | VULN-API-29-002..009 | Configure load/perf tests (5M findings/tenant), query budget enforcement, API SLO dashboards, and alerts for `vuln_list_latency` and `projection_lag`. | Perf suite integrated; dashboards live; alerts firing; runbooks updated. | +| DEVOPS-VULN-29-003 | TODO | DevOps Guild, Console Guild | WEB-VULN-29-004, CONSOLE-VULN-29-007 | Instrument analytics pipeline for Vuln Explorer (telemetry ingestion, query hashes), ensure compliance with privacy/PII guardrails, and update observability docs. | Telemetry pipeline operational; PII redaction verified; docs updated with checklist. | +| DEVOPS-VEX-30-001 | TODO | DevOps Guild, VEX Lens Guild | VEXLENS-30-009, ISSUER-30-005 | Provision CI, load tests, dashboards, alerts for VEX Lens and Issuer Directory (compute latency, disputed totals, signature verification rates). | CI/perf suites running; dashboards live; alerts configured; docs updated. | +| DEVOPS-AIAI-31-001 | TODO | DevOps Guild, Advisory AI Guild | AIAI-31-006..007 | Stand up CI pipelines, inference monitoring, privacy logging review, and perf dashboards for Advisory AI (summaries/conflicts/remediation). | CI covers golden outputs, telemetry dashboards live, privacy controls reviewed, alerts configured. | + +## Export Center +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-EXPORT-35-001 | BLOCKED (2025-10-29) | DevOps Guild, Exporter Service Guild | EXPORT-SVC-35-001..006 | Establish exporter CI pipeline (lint/test/perf smoke), configure object storage fixtures, seed Grafana dashboards, and document bootstrap steps. | CI pipeline running; smoke export job seeded; dashboards live; runbook updated. | +| DEVOPS-EXPORT-36-001 | TODO | DevOps Guild, Exporter Service Guild | DEVOPS-EXPORT-35-001, EXPORT-SVC-36-001..004 | Integrate Trivy compatibility validation, cosign signature checks, `trivy module db import` smoke tests, OCI distribution verification, and throughput/error dashboards. | CI executes cosign + Trivy import validation; OCI push smoke passes; dashboards/alerts configured. | +| DEVOPS-EXPORT-37-001 | TODO | DevOps Guild, Exporter Service Guild | DEVOPS-EXPORT-36-001, EXPORT-SVC-37-001..004 | Finalize exporter monitoring (failure alerts, verify metrics, retention jobs) and chaos/latency tests ahead of GA. | Alerts tuned; chaos tests documented; retention monitoring active; runbook updated. | + +## CLI Parity & Task Packs + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-CLI-41-001 | TODO | DevOps Guild, DevEx/CLI Guild | CLI-CORE-41-001 | Establish CLI build pipeline (multi-platform binaries, SBOM, checksums), parity matrix CI enforcement, and release artifact signing. | Build pipeline operational; SBOM/checksums published; parity gate failing on drift; docs updated. | +| DEVOPS-CLI-42-001 | TODO | DevOps Guild | DEVOPS-CLI-41-001, CLI-PARITY-41-001 | Add CLI golden output tests, parity diff automation, pack run CI harness, and artifact cache for remote mode. | Golden tests running; parity diff automation in CI; pack run harness executes sample packs; documentation updated. | +| DEVOPS-CLI-43-001 | DOING (2025-10-27) | DevOps Guild | DEVOPS-CLI-42-001, TASKRUN-42-001 | Finalize multi-platform release automation, SBOM signing, parity gate enforcement, and Task Pack chaos tests. | Release automation verified; SBOM signed; parity gate enforced; chaos tests documented. | +> 2025-10-27: Release pipeline now packages CLI multi-platform artefacts with SBOM/signature coverage and enforces the CLI parity gate (`ops/devops/check_cli_parity.py`). Task Pack chaos smoke still pending CLI pack command delivery. +| DEVOPS-CLI-43-002 | TODO | DevOps Guild, Task Runner Guild | CLI-PACKS-43-001, TASKRUN-43-001 | Implement Task Pack chaos smoke in CI (random failure injection, resume, sealed-mode toggle) and publish evidence bundles for review. | Chaos smoke job runs nightly; failures alert Slack; evidence stored in `out/pack-chaos`; runbook updated. | +| DEVOPS-CLI-43-003 | TODO | DevOps Guild, DevEx/CLI Guild | CLI-PARITY-41-001, CLI-PACKS-42-001 | Integrate CLI golden output/parity diff automation into release gating; export parity report artifact consumed by Console Downloads workspace. | `check_cli_parity.py` wired to compare parity matrix and CLI outputs; artifact uploaded; release fails on regressions. + +## Containerized Distribution (Epic 13) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-CONTAINERS-44-001 | TODO | DevOps Guild | DOCKER-44-001..003 | Automate multi-arch image builds with buildx, SBOM generation, cosign signing, and signature verification in CI. | Pipeline builds amd64/arm64; SBOMs pushed as referrers; cosign verify job passes. | +| DEVOPS-CONTAINERS-45-001 | TODO | DevOps Guild | HELM-45-001 | Add Compose and Helm smoke tests (fresh VM + kind cluster) to CI; publish test artifacts and logs. | CI jobs running; failures block releases; documentation updated. | +| DEVOPS-CONTAINERS-46-001 | TODO | DevOps Guild | DEPLOY-PACKS-43-001 | Build air-gap bundle generator (`src/Tools/make-airgap-bundle.sh`), produce signed bundle, and verify in CI using private registry. | Bundle artifact produced with signatures/checksums; verification job passes; instructions documented. | + +### Container Images (Epic 13) + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DOCKER-44-001 | TODO | DevOps Guild, Service Owners | DEVOPS-CLI-41-001 | Author multi-stage Dockerfiles for all core services (API, Console, Orchestrator, Task Runner, Conseiller, Excitator, Policy, Notify, Export, AI) with non-root users, read-only file systems, and health scripts. | Dockerfiles committed; images build successfully; container security scans clean; health endpoints reachable. | +| DOCKER-44-002 | TODO | DevOps Guild | DOCKER-44-001 | Generate SBOMs and cosign attestations for each image and integrate verification into CI. | SBOMs attached as OCI artifacts; cosign signatures published; CI verifies signatures prior to release. | +| DOCKER-44-003 | TODO | DevOps Guild | DOCKER-44-001 | Implement `/health/liveness`, `/health/readiness`, `/version`, `/metrics`, and ensure capability endpoint returns `merge=false` for Conseiller/Excitator. | Endpoints available across services; automated tests confirm responses; documentation updated with imposed rule reminder. | + +## Authority-Backed Scopes & Tenancy (Epic 14) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-TEN-47-001 | TODO | DevOps Guild | AUTH-TEN-47-001 | Add JWKS cache monitoring, signature verification regression tests, and token expiration chaos tests to CI. | CI verifies tokens using cached keys; chaos test for expired keys passes; documentation updated. | +| DEVOPS-TEN-48-001 | TODO | DevOps Guild | WEB-TEN-48-001 | Build integration tests to assert RLS enforcement, tenant-prefixed object storage, and audit event emission; set up lint to prevent raw SQL bypass. | Tests fail on cross-tenant access; lint enforced; dashboards capture audit events. | +| DEVOPS-TEN-49-001 | TODO | DevOps Guild | AUTH-TEN-49-001 | Deploy audit pipeline, scope usage metrics, JWKS outage chaos tests, and tenant load/perf benchmarks. | Audit pipeline live; metrics dashboards updated; chaos tests documented; perf benchmarks recorded. | + +## SDKs & OpenAPI (Epic 17) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-OAS-61-001 | TODO | DevOps Guild, API Contracts Guild | OAS-61-002 | Add CI stages for OpenAPI linting, validation, and compatibility diff; enforce gating on PRs. | Pipeline active; merge blocked on failures; documentation updated. | +| DEVOPS-OAS-61-002 | TODO | DevOps Guild, Contract Testing Guild | CONTR-62-002 | Integrate mock server + contract test suite into PR and nightly workflows; publish artifacts. | Tests run in CI; artifacts stored; failures alert. | +| DEVOPS-SDK-63-001 | TODO | DevOps Guild, SDK Release Guild | SDKREL-63-001 | Provision registry credentials, signing keys, and secure storage for SDK publishing pipelines. | Keys stored/rotated; publish pipeline authenticated; audit logs recorded. | +| DEVOPS-DEVPORT-63-001 | TODO | DevOps Guild, Developer Portal Guild | DEVPORT-62-001 | Automate developer portal build pipeline with caching, link & accessibility checks, performance budgets. | Pipeline enforced; reports archived; failures gate merges. | +| DEVOPS-DEVPORT-64-001 | TODO | DevOps Guild, DevPortal Offline Guild | DVOFF-64-001 | Schedule `devportal --offline` nightly builds with checksum validation and artifact retention policies. | Nightly job running; checksums published; retention policy documented. | + +## Attestor Console (Epic 19) +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| DEVOPS-ATTEST-73-001 | TODO | DevOps Guild, Attestor Service Guild | ATTESTOR-72-002 | Provision CI pipelines for attestor service (lint/test/security scan, seed data) and manage secrets for KMS drivers. | CI pipeline running; secrets stored securely; docs updated. | +| DEVOPS-ATTEST-73-002 | TODO | DevOps Guild, KMS Guild | KMS-72-001 | Establish secure storage for signing keys (vault integration, rotation schedule) and audit logging. | Key storage configured; rotation documented; audit logs verified. | +| DEVOPS-ATTEST-74-001 | TODO | DevOps Guild, Transparency Guild | TRANSP-74-001 | Deploy transparency log witness infrastructure and monitoring. | Witness service deployed; dashboards/alerts live. | +| DEVOPS-ATTEST-74-002 | TODO | DevOps Guild, Export Attestation Guild | EXPORT-ATTEST-74-001 | Integrate attestation bundle builds into release/offline pipelines with checksum verification. | Bundle job in CI; checksum verification passes; docs updated. | +| DEVOPS-ATTEST-75-001 | TODO | DevOps Guild, Observability Guild | ATTEST-VERIFY-74-001 | Add dashboards/alerts for signing latency, verification failures, key rotation events. | Dashboards live; alerts configured. | diff --git a/ops/devops/telemetry/package_offline_bundle.py b/ops/devops/telemetry/package_offline_bundle.py index 8c9a6232..41bbdd4d 100644 --- a/ops/devops/telemetry/package_offline_bundle.py +++ b/ops/devops/telemetry/package_offline_bundle.py @@ -1,136 +1,136 @@ -#!/usr/bin/env python3 -"""Package telemetry collector assets for offline/air-gapped installs. - -Outputs a tarball containing the collector configuration, Compose overlay, -Helm defaults, and operator README. A SHA-256 checksum sidecar is emitted, and -optional Cosign signing can be enabled with --sign. -""" -from __future__ import annotations - -import argparse -import hashlib -import os -import subprocess -import sys -import tarfile -from pathlib import Path -from typing import Iterable - -REPO_ROOT = Path(__file__).resolve().parents[3] -DEFAULT_OUTPUT = REPO_ROOT / "out" / "telemetry" / "telemetry-offline-bundle.tar.gz" -BUNDLE_CONTENTS: tuple[Path, ...] = ( - Path("deploy/telemetry/README.md"), - Path("deploy/telemetry/otel-collector-config.yaml"), - Path("deploy/telemetry/storage/README.md"), - Path("deploy/telemetry/storage/prometheus.yaml"), - Path("deploy/telemetry/storage/tempo.yaml"), - Path("deploy/telemetry/storage/loki.yaml"), - Path("deploy/telemetry/storage/tenants/tempo-overrides.yaml"), - Path("deploy/telemetry/storage/tenants/loki-overrides.yaml"), - Path("deploy/helm/stellaops/files/otel-collector-config.yaml"), - Path("deploy/helm/stellaops/values.yaml"), - Path("deploy/helm/stellaops/templates/otel-collector.yaml"), - Path("deploy/compose/docker-compose.telemetry.yaml"), - Path("deploy/compose/docker-compose.telemetry-storage.yaml"), - Path("docs/ops/telemetry-collector.md"), - Path("docs/ops/telemetry-storage.md"), -) - - -def compute_sha256(path: Path) -> str: - sha = hashlib.sha256() - with path.open("rb") as handle: - for chunk in iter(lambda: handle.read(1024 * 1024), b""): - sha.update(chunk) - return sha.hexdigest() - - -def validate_files(paths: Iterable[Path]) -> None: - missing = [str(p) for p in paths if not (REPO_ROOT / p).exists()] - if missing: - raise FileNotFoundError(f"Missing bundle artefacts: {', '.join(missing)}") - - -def create_bundle(output_path: Path) -> Path: - output_path.parent.mkdir(parents=True, exist_ok=True) - with tarfile.open(output_path, "w:gz") as tar: - for rel_path in BUNDLE_CONTENTS: - abs_path = REPO_ROOT / rel_path - tar.add(abs_path, arcname=str(rel_path)) - return output_path - - -def write_checksum(bundle_path: Path) -> Path: - digest = compute_sha256(bundle_path) - sha_path = bundle_path.with_suffix(bundle_path.suffix + ".sha256") - sha_path.write_text(f"{digest} {bundle_path.name}\n", encoding="utf-8") - return sha_path - - -def cosign_sign(bundle_path: Path, key_ref: str | None, identity_token: str | None) -> None: - cmd = ["cosign", "sign-blob", "--yes", str(bundle_path)] - if key_ref: - cmd.extend(["--key", key_ref]) - env = os.environ.copy() - if identity_token: - env["COSIGN_IDENTITY_TOKEN"] = identity_token - try: - subprocess.run(cmd, check=True, env=env) - except FileNotFoundError as exc: - raise RuntimeError("cosign not found on PATH; install cosign or omit --sign") from exc - except subprocess.CalledProcessError as exc: - raise RuntimeError(f"cosign sign-blob failed: {exc}") from exc - - -def parse_args(argv: list[str] | None = None) -> argparse.Namespace: - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument( - "--output", - type=Path, - default=DEFAULT_OUTPUT, - help=f"Output bundle path (default: {DEFAULT_OUTPUT})", - ) - parser.add_argument( - "--sign", - action="store_true", - help="Sign the bundle using cosign (requires cosign on PATH)", - ) - parser.add_argument( - "--cosign-key", - type=str, - default=os.environ.get("COSIGN_KEY_REF"), - help="Cosign key reference (file:..., azurekms://..., etc.)", - ) - parser.add_argument( - "--identity-token", - type=str, - default=os.environ.get("COSIGN_IDENTITY_TOKEN"), - help="OIDC identity token for keyless signing", - ) - return parser.parse_args(argv) - - -def main(argv: list[str] | None = None) -> int: - args = parse_args(argv) - validate_files(BUNDLE_CONTENTS) - - bundle_path = args.output.resolve() - print(f"[*] Creating telemetry bundle at {bundle_path}") - create_bundle(bundle_path) - sha_path = write_checksum(bundle_path) - print(f"[✓] SHA-256 written to {sha_path}") - - if args.sign: - print("[*] Signing bundle with cosign") - cosign_sign(bundle_path, args.cosign_key, args.identity_token) - sig_path = bundle_path.with_suffix(bundle_path.suffix + ".sig") - if sig_path.exists(): - print(f"[✓] Cosign signature written to {sig_path}") - else: - print("[!] Cosign completed but signature file not found (ensure cosign version >= 2.2)") - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) +#!/usr/bin/env python3 +"""Package telemetry collector assets for offline/air-gapped installs. + +Outputs a tarball containing the collector configuration, Compose overlay, +Helm defaults, and operator README. A SHA-256 checksum sidecar is emitted, and +optional Cosign signing can be enabled with --sign. +""" +from __future__ import annotations + +import argparse +import hashlib +import os +import subprocess +import sys +import tarfile +from pathlib import Path +from typing import Iterable + +REPO_ROOT = Path(__file__).resolve().parents[3] +DEFAULT_OUTPUT = REPO_ROOT / "out" / "telemetry" / "telemetry-offline-bundle.tar.gz" +BUNDLE_CONTENTS: tuple[Path, ...] = ( + Path("deploy/telemetry/README.md"), + Path("deploy/telemetry/otel-collector-config.yaml"), + Path("deploy/telemetry/storage/README.md"), + Path("deploy/telemetry/storage/prometheus.yaml"), + Path("deploy/telemetry/storage/tempo.yaml"), + Path("deploy/telemetry/storage/loki.yaml"), + Path("deploy/telemetry/storage/tenants/tempo-overrides.yaml"), + Path("deploy/telemetry/storage/tenants/loki-overrides.yaml"), + Path("deploy/helm/stellaops/files/otel-collector-config.yaml"), + Path("deploy/helm/stellaops/values.yaml"), + Path("deploy/helm/stellaops/templates/otel-collector.yaml"), + Path("deploy/compose/docker-compose.telemetry.yaml"), + Path("deploy/compose/docker-compose.telemetry-storage.yaml"), + Path("docs/modules/telemetry/operations/collector.md"), + Path("docs/modules/telemetry/operations/storage.md"), +) + + +def compute_sha256(path: Path) -> str: + sha = hashlib.sha256() + with path.open("rb") as handle: + for chunk in iter(lambda: handle.read(1024 * 1024), b""): + sha.update(chunk) + return sha.hexdigest() + + +def validate_files(paths: Iterable[Path]) -> None: + missing = [str(p) for p in paths if not (REPO_ROOT / p).exists()] + if missing: + raise FileNotFoundError(f"Missing bundle artefacts: {', '.join(missing)}") + + +def create_bundle(output_path: Path) -> Path: + output_path.parent.mkdir(parents=True, exist_ok=True) + with tarfile.open(output_path, "w:gz") as tar: + for rel_path in BUNDLE_CONTENTS: + abs_path = REPO_ROOT / rel_path + tar.add(abs_path, arcname=str(rel_path)) + return output_path + + +def write_checksum(bundle_path: Path) -> Path: + digest = compute_sha256(bundle_path) + sha_path = bundle_path.with_suffix(bundle_path.suffix + ".sha256") + sha_path.write_text(f"{digest} {bundle_path.name}\n", encoding="utf-8") + return sha_path + + +def cosign_sign(bundle_path: Path, key_ref: str | None, identity_token: str | None) -> None: + cmd = ["cosign", "sign-blob", "--yes", str(bundle_path)] + if key_ref: + cmd.extend(["--key", key_ref]) + env = os.environ.copy() + if identity_token: + env["COSIGN_IDENTITY_TOKEN"] = identity_token + try: + subprocess.run(cmd, check=True, env=env) + except FileNotFoundError as exc: + raise RuntimeError("cosign not found on PATH; install cosign or omit --sign") from exc + except subprocess.CalledProcessError as exc: + raise RuntimeError(f"cosign sign-blob failed: {exc}") from exc + + +def parse_args(argv: list[str] | None = None) -> argparse.Namespace: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "--output", + type=Path, + default=DEFAULT_OUTPUT, + help=f"Output bundle path (default: {DEFAULT_OUTPUT})", + ) + parser.add_argument( + "--sign", + action="store_true", + help="Sign the bundle using cosign (requires cosign on PATH)", + ) + parser.add_argument( + "--cosign-key", + type=str, + default=os.environ.get("COSIGN_KEY_REF"), + help="Cosign key reference (file:..., azurekms://..., etc.)", + ) + parser.add_argument( + "--identity-token", + type=str, + default=os.environ.get("COSIGN_IDENTITY_TOKEN"), + help="OIDC identity token for keyless signing", + ) + return parser.parse_args(argv) + + +def main(argv: list[str] | None = None) -> int: + args = parse_args(argv) + validate_files(BUNDLE_CONTENTS) + + bundle_path = args.output.resolve() + print(f"[*] Creating telemetry bundle at {bundle_path}") + create_bundle(bundle_path) + sha_path = write_checksum(bundle_path) + print(f"[✓] SHA-256 written to {sha_path}") + + if args.sign: + print("[*] Signing bundle with cosign") + cosign_sign(bundle_path, args.cosign_key, args.identity_token) + sig_path = bundle_path.with_suffix(bundle_path.suffix + ".sig") + if sig_path.exists(): + print(f"[✓] Cosign signature written to {sig_path}") + else: + print("[!] Cosign completed but signature file not found (ensure cosign version >= 2.2)") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/ops/licensing/AGENTS.md b/ops/licensing/AGENTS.md index d1cce675..23ef1108 100644 --- a/ops/licensing/AGENTS.md +++ b/ops/licensing/AGENTS.md @@ -1,4 +1,4 @@ -# Licensing & Registry Access — Agent Charter - -## Mission -Implement licensing token service and registry access workflows described in `docs/ARCHITECTURE_DEVOPS.md`. +# Licensing & Registry Access — Agent Charter + +## Mission +Implement licensing token service and registry access workflows described in `docs/modules/devops/ARCHITECTURE.md`. diff --git a/ops/offline-kit/AGENTS.md b/ops/offline-kit/AGENTS.md index e0962c1d..597dbc12 100644 --- a/ops/offline-kit/AGENTS.md +++ b/ops/offline-kit/AGENTS.md @@ -1,4 +1,4 @@ -# Offline Kit — Agent Charter - -## Mission -Package Offline Update Kit per `docs/ARCHITECTURE_DEVOPS.md` and `docs/24_OFFLINE_KIT.md` with deterministic digests and import tooling. +# Offline Kit — Agent Charter + +## Mission +Package Offline Update Kit per `docs/modules/devops/ARCHITECTURE.md` and `docs/24_OFFLINE_KIT.md` with deterministic digests and import tooling. diff --git a/ops/offline-kit/run-python-analyzer-smoke.sh b/ops/offline-kit/run-python-analyzer-smoke.sh index 535b92e9..cb4712f9 100644 --- a/ops/offline-kit/run-python-analyzer-smoke.sh +++ b/ops/offline-kit/run-python-analyzer-smoke.sh @@ -31,6 +31,6 @@ fi repo_root_win="$(to_win_path "$repo_root")" exec dotnet run \ - --project "${repo_root_win}/tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj" \ + --project "${repo_root_win}/src/Tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj" \ --configuration Release \ -- --repo-root "${repo_root_win}" diff --git a/out/analyzers/python/StellaOps.Auth.Abstractions.xml b/out/analyzers/python/StellaOps.Auth.Abstractions.xml deleted file mode 100644 index d533443e..00000000 --- a/out/analyzers/python/StellaOps.Auth.Abstractions.xml +++ /dev/null @@ -1,422 +0,0 @@ - - - - StellaOps.Auth.Abstractions - - - - - Canonical telemetry metadata for the StellaOps Authority stack. - - - - - service.name resource attribute recorded by Authority components. - - - - - service.namespace resource attribute aligning Authority with other StellaOps services. - - - - - Activity source identifier used by Authority instrumentation. - - - - - Meter name used by Authority instrumentation. - - - - - Builds the default set of resource attributes (service name/namespace/version). - - Optional assembly used to resolve the service version. - - - - Resolves the service version string from the provided assembly (defaults to the Authority telemetry assembly). - - - - - Represents an IP network expressed in CIDR notation. - - - - - Initialises a new . - - Canonical network address with host bits zeroed. - Prefix length (0-32 for IPv4, 0-128 for IPv6). - - - - Canonical network address with host bits zeroed. - - - - - Prefix length. - - - - - Attempts to parse the supplied value as CIDR notation or a single IP address. - - Thrown when the input is not recognised. - - - - Attempts to parse the supplied value as CIDR notation or a single IP address. - - - - - Determines whether the provided address belongs to this network. - - - - - - - - Evaluates remote addresses against configured network masks. - - - - - Creates a matcher from raw CIDR strings. - - Sequence of CIDR entries or IP addresses. - Thrown when a value cannot be parsed. - - - - Creates a matcher from already parsed masks. - - Sequence of network masks. - - - - Gets a matcher that allows every address. - - - - - Gets a matcher that denies every address (no masks configured). - - - - - Indicates whether this matcher has no masks configured and does not allow all. - - - - - Returns the configured masks. - - - - - Checks whether the provided address matches any of the configured masks. - - Remote address to test. - true when the address is allowed. - - - - Default authentication constants used by StellaOps resource servers and clients. - - - - - Default authentication scheme for StellaOps bearer tokens. - - - - - Logical authentication type attached to . - - - - - Policy prefix applied to named authorization policies. - - - - - Canonical claim type identifiers used across StellaOps services. - - - - - Subject identifier claim (maps to sub in JWTs). - - - - - StellaOps tenant identifier claim (multi-tenant deployments). - - - - - OAuth2/OIDC client identifier claim (maps to client_id). - - - - - Unique token identifier claim (maps to jti). - - - - - Authentication method reference claim (amr). - - - - - Space separated scope list (scope). - - - - - Individual scope items (scp). - - - - - OAuth2 resource audiences (aud). - - - - - Identity provider hint for downstream services. - - - - - Session identifier claim (sid). - - - - - Fluent helper used to construct instances that follow StellaOps conventions. - - - - - Adds or replaces the canonical subject identifier. - - - - - Adds or replaces the canonical client identifier. - - - - - Adds or replaces the tenant identifier claim. - - - - - Adds or replaces the user display name claim. - - - - - Adds or replaces the identity provider claim. - - - - - Adds or replaces the session identifier claim. - - - - - Adds or replaces the token identifier claim. - - - - - Adds or replaces the authentication method reference claim. - - - - - Sets the name claim type appended when building the . - - - - - Sets the role claim type appended when building the . - - - - - Sets the authentication type stamped on the . - - - - - Registers the supplied scopes (normalised to lower-case, deduplicated, sorted). - - - - - Registers the supplied audiences (trimmed, deduplicated, sorted). - - - - - Adds a single audience. - - - - - Adds an arbitrary claim (no deduplication is performed). - - - - - Adds multiple claims (incoming claims are cloned to enforce value trimming). - - - - - Adds an iat (issued at) claim using Unix time seconds. - - - - - Adds an nbf (not before) claim using Unix time seconds. - - - - - Adds an exp (expires) claim using Unix time seconds. - - - - - Returns the normalised scope list (deduplicated + sorted). - - - - - Returns the normalised audience list (deduplicated + sorted). - - - - - Builds the immutable instance based on the registered data. - - - - - Factory helpers for returning RFC 7807 problem responses using StellaOps conventions. - - - - - Produces a 401 problem response indicating authentication is required. - - - - - Produces a 401 problem response for invalid, expired, or revoked tokens. - - - - - Produces a 403 problem response when access is denied. - - - - - Produces a 403 problem response for insufficient scopes. - - - - - Canonical scope names supported by StellaOps services. - - - - - Scope required to trigger Concelier jobs. - - - - - Scope required to manage Concelier merge operations. - - - - - Scope granting administrative access to Authority user management. - - - - - Scope granting administrative access to Authority client registrations. - - - - - Scope granting read-only access to Authority audit logs. - - - - - Synthetic scope representing trusted network bypass. - - - - - Scope granting read-only access to raw advisory ingestion data. - - - - - Scope granting write access for raw advisory ingestion. - - - - - Scope granting read-only access to raw VEX ingestion data. - - - - - Scope granting write access for raw VEX ingestion. - - - - - Scope granting permission to execute aggregation-only contract verification. - - - - - Normalises a scope string (trim/convert to lower case). - - Scope raw value. - Normalised scope or null when the input is blank. - - - - Checks whether the provided scope is registered as a built-in StellaOps scope. - - - - - Returns the full set of built-in scopes. - - - - diff --git a/out/analyzers/python/StellaOps.Auth.Client.xml b/out/analyzers/python/StellaOps.Auth.Client.xml deleted file mode 100644 index a3b44557..00000000 --- a/out/analyzers/python/StellaOps.Auth.Client.xml +++ /dev/null @@ -1,233 +0,0 @@ - - - - StellaOps.Auth.Client - - - - - File-based token cache suitable for CLI/offline usage. - - - - - In-memory token cache suitable for service scenarios. - - - - - Abstraction for caching StellaOps tokens. - - - - - Retrieves a cached token entry, if present. - - - - - Stores or updates a token entry for the specified key. - - - - - Removes the cached entry for the specified key. - - - - - Abstraction for requesting tokens from StellaOps Authority. - - - - - Requests an access token using the resource owner password credentials flow. - - - - - Requests an access token using the client credentials flow. - - - - - Retrieves the cached JWKS document. - - - - - Retrieves a cached token entry. - - - - - Persists a token entry in the cache. - - - - - Removes a cached entry. - - - - - DI helpers for the StellaOps auth client. - - - - - Registers the StellaOps auth client with the provided configuration. - - - - - Registers a file-backed token cache implementation. - - - - - Options controlling the StellaOps authentication client. - - - - - Authority (issuer) base URL. - - - - - OAuth client identifier (optional for password flow). - - - - - OAuth client secret (optional for public clients). - - - - - Default scopes requested for flows that do not explicitly override them. - - - - - Retry delays applied by HTTP retry policy (empty uses defaults). - - - - - Gets or sets a value indicating whether HTTP retry policies are enabled. - - - - - Timeout applied to discovery and token HTTP requests. - - - - - Lifetime of cached discovery metadata. - - - - - Lifetime of cached JWKS metadata. - - - - - Buffer applied when determining cache expiration (default: 30 seconds). - - - - - Gets or sets a value indicating whether cached discovery/JWKS responses may be served when the Authority is unreachable. - - - - - Additional tolerance window during which stale cache entries remain valid if offline fallback is allowed. - - - - - Parsed Authority URI (populated after validation). - - - - - Normalised scope list (populated after validation). - - - - - Normalised retry delays (populated after validation). - - - - - Validates required values and normalises scope entries. - - - - - Caches Authority discovery metadata. - - - - - Minimal OpenID Connect configuration representation. - - - - - Minimal OpenID Connect configuration representation. - - - - - Caches JWKS documents for Authority. - - - - - Represents a cached token entry. - - - - - Represents a cached token entry. - - - - - Determines whether the token is expired given the provided . - - - - - Creates a copy with scopes normalised. - - - - - Default implementation of . - - - - - Represents an issued token with metadata. - - - - - Represents an issued token with metadata. - - - - - Converts the result to a cache entry. - - - - diff --git a/out/analyzers/python/StellaOps.Scanner.Analyzers.Lang.Python.deps.json b/out/analyzers/python/StellaOps.Scanner.Analyzers.Lang.Python.deps.json deleted file mode 100644 index d49edca0..00000000 --- a/out/analyzers/python/StellaOps.Scanner.Analyzers.Lang.Python.deps.json +++ /dev/null @@ -1,858 +0,0 @@ -{ - "runtimeTarget": { - "name": ".NETCoreApp,Version=v10.0", - "signature": "" - }, - "compilationOptions": {}, - "targets": { - ".NETCoreApp,Version=v10.0": { - "StellaOps.Scanner.Analyzers.Lang.Python/1.0.0": { - "dependencies": { - "SharpCompress": "0.41.0", - "StellaOps.Scanner.Analyzers.Lang": "1.0.0" - }, - "runtime": { - "StellaOps.Scanner.Analyzers.Lang.Python.dll": {} - } - }, - "Konscious.Security.Cryptography.Argon2/1.3.1": { - "dependencies": { - "Konscious.Security.Cryptography.Blake2": "1.1.1" - }, - "runtime": { - "lib/net8.0/Konscious.Security.Cryptography.Argon2.dll": { - "assemblyVersion": "1.3.1.0", - "fileVersion": "1.3.1.0" - } - } - }, - "Konscious.Security.Cryptography.Blake2/1.1.1": { - "runtime": { - "lib/net8.0/Konscious.Security.Cryptography.Blake2.dll": { - "assemblyVersion": "1.1.1.0", - "fileVersion": "1.1.1.0" - } - } - }, - "Microsoft.Extensions.Configuration/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Configuration.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Configuration.Abstractions/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Configuration.Abstractions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Configuration.Binder/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Configuration.Binder.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Configuration.EnvironmentVariables/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Configuration.EnvironmentVariables.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Configuration.FileExtensions/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.FileProviders.Physical": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Configuration.FileExtensions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Configuration.Json/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Configuration.Json.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.DependencyInjection/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.DependencyInjection.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": { - "runtime": { - "lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Diagnostics/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Options.ConfigurationExtensions": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Diagnostics.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Diagnostics.Abstractions/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.FileProviders.Abstractions/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.FileProviders.Abstractions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.FileProviders.Physical/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.FileSystemGlobbing": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.FileProviders.Physical.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.FileSystemGlobbing/10.0.0-rc.2.25502.107": { - "runtime": { - "lib/net10.0/Microsoft.Extensions.FileSystemGlobbing.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Http/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Diagnostics": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Logging": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Http.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Http.Polly/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Http": "10.0.0-rc.2.25502.107", - "Polly": "7.2.4", - "Polly.Extensions.Http": "3.0.0" - }, - "runtime": { - "lib/netstandard2.0/Microsoft.Extensions.Http.Polly.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Logging/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.DependencyInjection": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Logging.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Options/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Options.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Options.ConfigurationExtensions/10.0.0-rc.2.25502.107": { - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Binder": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107" - }, - "runtime": { - "lib/net10.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.Extensions.Primitives/10.0.0-rc.2.25502.107": { - "runtime": { - "lib/net10.0/Microsoft.Extensions.Primitives.dll": { - "assemblyVersion": "10.0.0.0", - "fileVersion": "10.0.25.50307" - } - } - }, - "Microsoft.IdentityModel.Abstractions/8.14.0": { - "runtime": { - "lib/net9.0/Microsoft.IdentityModel.Abstractions.dll": { - "assemblyVersion": "8.14.0.0", - "fileVersion": "8.14.0.60815" - } - } - }, - "Microsoft.IdentityModel.JsonWebTokens/7.2.0": { - "dependencies": { - "Microsoft.IdentityModel.Tokens": "8.14.0" - }, - "runtime": { - "lib/net8.0/Microsoft.IdentityModel.JsonWebTokens.dll": { - "assemblyVersion": "7.2.0.0", - "fileVersion": "7.2.0.50110" - } - } - }, - "Microsoft.IdentityModel.Logging/8.14.0": { - "dependencies": { - "Microsoft.IdentityModel.Abstractions": "8.14.0" - }, - "runtime": { - "lib/net9.0/Microsoft.IdentityModel.Logging.dll": { - "assemblyVersion": "8.14.0.0", - "fileVersion": "8.14.0.60815" - } - } - }, - "Microsoft.IdentityModel.Tokens/8.14.0": { - "dependencies": { - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.IdentityModel.Logging": "8.14.0" - }, - "runtime": { - "lib/net9.0/Microsoft.IdentityModel.Tokens.dll": { - "assemblyVersion": "8.14.0.0", - "fileVersion": "8.14.0.60815" - } - } - }, - "NetEscapades.Configuration.Yaml/2.1.0": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-rc.2.25502.107", - "YamlDotNet": "9.1.0" - }, - "runtime": { - "lib/netstandard2.0/NetEscapades.Configuration.Yaml.dll": { - "assemblyVersion": "2.1.0.0", - "fileVersion": "2.1.0.0" - } - } - }, - "Pipelines.Sockets.Unofficial/2.2.8": { - "runtime": { - "lib/net5.0/Pipelines.Sockets.Unofficial.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "2.2.8.1080" - } - } - }, - "Polly/7.2.4": { - "runtime": { - "lib/netstandard2.0/Polly.dll": { - "assemblyVersion": "7.0.0.0", - "fileVersion": "7.2.4.982" - } - } - }, - "Polly.Extensions.Http/3.0.0": { - "dependencies": { - "Polly": "7.2.4" - }, - "runtime": { - "lib/netstandard2.0/Polly.Extensions.Http.dll": { - "assemblyVersion": "3.0.0.0", - "fileVersion": "3.0.0.0" - } - } - }, - "SharpCompress/0.41.0": { - "dependencies": { - "ZstdSharp.Port": "0.8.6" - }, - "runtime": { - "lib/net8.0/SharpCompress.dll": { - "assemblyVersion": "0.41.0.0", - "fileVersion": "0.41.0.0" - } - } - }, - "StackExchange.Redis/2.8.24": { - "dependencies": { - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "Pipelines.Sockets.Unofficial": "2.2.8" - }, - "runtime": { - "lib/net8.0/StackExchange.Redis.dll": { - "assemblyVersion": "2.0.0.0", - "fileVersion": "2.8.24.3255" - } - } - }, - "System.IdentityModel.Tokens.Jwt/7.2.0": { - "dependencies": { - "Microsoft.IdentityModel.JsonWebTokens": "7.2.0", - "Microsoft.IdentityModel.Tokens": "8.14.0" - }, - "runtime": { - "lib/net8.0/System.IdentityModel.Tokens.Jwt.dll": { - "assemblyVersion": "7.2.0.0", - "fileVersion": "7.2.0.50110" - } - } - }, - "YamlDotNet/9.1.0": { - "runtime": { - "lib/netstandard2.1/YamlDotNet.dll": { - "assemblyVersion": "9.0.0.0", - "fileVersion": "9.1.0.0" - } - } - }, - "ZstdSharp.Port/0.8.6": { - "runtime": { - "lib/net9.0/ZstdSharp.dll": { - "assemblyVersion": "0.8.6.0", - "fileVersion": "0.8.6.0" - } - } - }, - "StellaOps.Auth.Abstractions/1.0.0-preview.1": { - "dependencies": { - "SharpCompress": "0.41.0" - }, - "runtime": { - "StellaOps.Auth.Abstractions.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Auth.Client/1.0.0-preview.1": { - "dependencies": { - "Microsoft.Extensions.Http.Polly": "10.0.0-rc.2.25502.107", - "Microsoft.IdentityModel.Tokens": "8.14.0", - "SharpCompress": "0.41.0", - "StellaOps.Auth.Abstractions": "1.0.0-preview.1", - "StellaOps.Configuration": "1.0.0" - }, - "runtime": { - "StellaOps.Auth.Client.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Auth.Security/1.0.0-preview.1": { - "dependencies": { - "Microsoft.IdentityModel.Tokens": "8.14.0", - "SharpCompress": "0.41.0", - "StackExchange.Redis": "2.8.24", - "System.IdentityModel.Tokens.Jwt": "7.2.0" - }, - "runtime": { - "StellaOps.Auth.Security.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Authority.Plugins.Abstractions/1.0.0": { - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "SharpCompress": "0.41.0", - "StellaOps.Auth.Abstractions": "1.0.0-preview.1", - "StellaOps.Cryptography": "1.0.0" - }, - "runtime": { - "StellaOps.Authority.Plugins.Abstractions.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Configuration/1.0.0": { - "dependencies": { - "Microsoft.Extensions.Configuration": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Binder": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.FileExtensions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Configuration.Json": "10.0.0-rc.2.25502.107", - "NetEscapades.Configuration.Yaml": "2.1.0", - "SharpCompress": "0.41.0", - "StellaOps.Authority.Plugins.Abstractions": "1.0.0", - "StellaOps.Cryptography": "1.0.0" - }, - "runtime": { - "StellaOps.Configuration.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Cryptography/1.0.0": { - "dependencies": { - "Konscious.Security.Cryptography.Argon2": "1.3.1", - "Microsoft.IdentityModel.Tokens": "8.14.0", - "SharpCompress": "0.41.0" - }, - "runtime": { - "StellaOps.Cryptography.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.DependencyInjection/1.0.0": { - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "SharpCompress": "0.41.0" - }, - "runtime": { - "StellaOps.DependencyInjection.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Plugin/1.0.0": { - "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "SharpCompress": "0.41.0", - "StellaOps.DependencyInjection": "1.0.0" - }, - "runtime": { - "StellaOps.Plugin.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Scanner.Analyzers.Lang/1.0.0": { - "dependencies": { - "SharpCompress": "0.41.0", - "StellaOps.Plugin": "1.0.0", - "StellaOps.Scanner.Core": "1.0.0" - }, - "runtime": { - "StellaOps.Scanner.Analyzers.Lang.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - }, - "StellaOps.Scanner.Core/1.0.0": { - "dependencies": { - "Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107", - "Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107", - "SharpCompress": "0.41.0", - "StellaOps.Auth.Client": "1.0.0-preview.1", - "StellaOps.Auth.Security": "1.0.0-preview.1" - }, - "runtime": { - "StellaOps.Scanner.Core.dll": { - "assemblyVersion": "1.0.0.0", - "fileVersion": "1.0.0.0" - } - } - } - } - }, - "libraries": { - "StellaOps.Scanner.Analyzers.Lang.Python/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "Konscious.Security.Cryptography.Argon2/1.3.1": { - "type": "package", - "serviceable": true, - "sha512": "sha512-T+OAGwzYYXftahpOxO7J4xA5K6urxwGnWQf3M+Jpi+76Azv/0T3M5SuN+h7/QvXuiqNw3ZEZ5QqVLI5ygDAylw==", - "path": "konscious.security.cryptography.argon2/1.3.1", - "hashPath": "konscious.security.cryptography.argon2.1.3.1.nupkg.sha512" - }, - "Konscious.Security.Cryptography.Blake2/1.1.1": { - "type": "package", - "serviceable": true, - "sha512": "sha512-odwOyzj/J/lHJZNwFWJGU/LRecBShupAJ2S8TQqZfhUe9niHzu/voBYK5wuVKsvSpzbfupKQYZguVyIk1sgOkQ==", - "path": "konscious.security.cryptography.blake2/1.1.1", - "hashPath": "konscious.security.cryptography.blake2.1.1.1.nupkg.sha512" - }, - "Microsoft.Extensions.Configuration/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-273Ggibh3DdVrj47ENbUGIirOiqmLTAizpkvOD584Ps6NL/CMXPzesijnJgsjp7Fv/UCp69FKYBaSxZZ3q5R9g==", - "path": "microsoft.extensions.configuration/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.configuration.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Configuration.Abstractions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-H+i/Qy30Rg/K9BcW2Z6DCHPCzwMH3bCwNOjEz31shWTUDK8GeeeMnrKVusprTcRA2Y6yPST+hg2zc3whPEs14Q==", - "path": "microsoft.extensions.configuration.abstractions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.configuration.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Configuration.Binder/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-aA6/V6lw1Gueyb1PqhHAl/i/qUUuv+Fusfk4oaMOzzOjspBkYtPpNHCmml/0t1x0/DnZoed+u2WwpP+mSwd8Dg==", - "path": "microsoft.extensions.configuration.binder/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.configuration.binder.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Configuration.EnvironmentVariables/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-2SV60IUAWfluZv2YHNZ+nUOljYHGIsy96FpJs+N9/bgKDYs9qr6DdzPeIhiHrz+XvRzbybvcwtTBf5dKrYN4oA==", - "path": "microsoft.extensions.configuration.environmentvariables/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.configuration.environmentvariables.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Configuration.FileExtensions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-5KrgXSTFR8cFLmDXXoT7GLVvDyHNw0Z9xG4doD78Q/HdlAR4jiMzmLLS9GFXrPGopmC6qqEZr2VBJHEu16INcA==", - "path": "microsoft.extensions.configuration.fileextensions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.configuration.fileextensions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Configuration.Json/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-USwHuFz4BFKoaqSydHWH/d7Mr+fVsAh9S0S9pdsdHro1IixMbqQ9Gpo2sEZf25e3tZSq/ts6XsVmrQWmxmDhYA==", - "path": "microsoft.extensions.configuration.json/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.configuration.json.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.DependencyInjection/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-mDw80K98jBWCyLFCra51PRv+Ttnjse1lZIzXEFybKby0/ajBFTEeHj/4r/QJexmb8Uun0yaFH1HlFtmHP1YEVA==", - "path": "microsoft.extensions.dependencyinjection/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.dependencyinjection.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==", - "path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Diagnostics/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-tQfQFXI+ZQcL2RzDarDLx3Amh0WCp1KPGp1ie3y/CMV5hDhEq98WTmcMoXrFY0GkYLEaCQlVi2A6qVLcooG2Ow==", - "path": "microsoft.extensions.diagnostics/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.diagnostics.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Diagnostics.Abstractions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-x6XVv3RiwOlN2unjyX/Zat0gI0HiRoDDdjkwBCwsMftYWpbJu4SiyRwDbrv2zAF8v8nbEEvcWi3/pUxZfaqLQw==", - "path": "microsoft.extensions.diagnostics.abstractions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.diagnostics.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.FileProviders.Abstractions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-dOpmW14MkOZIwV6269iXhoMp6alCHBoxqCR4pJ37GLjFaBIyzsIy+Ra8tsGmjHtFvEHKq0JRDIsb1PUkrK+yxw==", - "path": "microsoft.extensions.fileproviders.abstractions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.fileproviders.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.FileProviders.Physical/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-3+RiR6TEakDL0dCUqR7PjFffyrVMLdx/vAVBiN1mGmwScKYCTePIkYVkWsX85CTKh7R9J4M9C1MHzVdjbKcg3g==", - "path": "microsoft.extensions.fileproviders.physical/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.fileproviders.physical.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.FileSystemGlobbing/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-XtcPOKB7sMFzj8SxaOglZV3eaqZ1GxUMVZTwaz4pRpBt0S45ghb836uUej4YaI8EzsnUJoqzOIKrTW4CDJMfVw==", - "path": "microsoft.extensions.filesystemglobbing/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.filesystemglobbing.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Http/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-d60bvi/NpzkpVlSpxZqOfdjX1hrQgL/byWVc3PryjbmB7zvfLtqQbYifjEWToqtS0Fb1rGnkuVI5JEdOnK1tNQ==", - "path": "microsoft.extensions.http/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.http.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Http.Polly/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-aY5vLcrhdXCHsCjYI2lNwfat2vdSuiPs0FFZiy7IM6zcyqdxaefG8J8ezTKkZyiuAtznjVJJT70B660l/WlsxA==", - "path": "microsoft.extensions.http.polly/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.http.polly.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Logging/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-q2C5gq86qkTmcYSJJSnw8sgTUyuqENYSOjk/NOYjHnYlKSrK3oI9Rjv1bWFpx2I3Btq9ZBEJb9aMM+IUQ0PvZA==", - "path": "microsoft.extensions.logging/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.logging.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==", - "path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Options/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-Ib6BCCjisp7ZUdhtNpSulFO0ODhz/IE4ZZd8OCqQWoRs363BQ0QOZi9KwpqpiEWo51S0kIXWqNicDPGXwpt9pQ==", - "path": "microsoft.extensions.options/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.options.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Options.ConfigurationExtensions/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-MFbT8+JKX49YCXEFvlZDzQzI/R3QKzRZlb4dSud+569cMgA9hWbndjWWvOgGASoRcXynGRrBSq1Bw3PeCsB5/Q==", - "path": "microsoft.extensions.options.configurationextensions/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.options.configurationextensions.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.Extensions.Primitives/10.0.0-rc.2.25502.107": { - "type": "package", - "serviceable": true, - "sha512": "sha512-9pm2zqqn5u/OsKs2zgkhJEQQeMx9KkVOWPdHrs7Kt5sfpk+eIh/gmpi/mMH/ljS2T/PFsFdCEtm+GS/6l7zoZA==", - "path": "microsoft.extensions.primitives/10.0.0-rc.2.25502.107", - "hashPath": "microsoft.extensions.primitives.10.0.0-rc.2.25502.107.nupkg.sha512" - }, - "Microsoft.IdentityModel.Abstractions/8.14.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-iwbCpSjD3ehfTwBhtSNEtKPK0ICun6ov7Ibx6ISNA9bfwIyzI2Siwyi9eJFCJBwxowK9xcA1mj+jBWiigeqgcQ==", - "path": "microsoft.identitymodel.abstractions/8.14.0", - "hashPath": "microsoft.identitymodel.abstractions.8.14.0.nupkg.sha512" - }, - "Microsoft.IdentityModel.JsonWebTokens/7.2.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-zLFA9IBxDWw6Y1nz2PPZyQvF+ZZ4aW1pwgtwusQB39lgxOc2xVqZ8gitsuT1rwyuIbchGOWbax4fsJ8OgGRxSQ==", - "path": "microsoft.identitymodel.jsonwebtokens/7.2.0", - "hashPath": "microsoft.identitymodel.jsonwebtokens.7.2.0.nupkg.sha512" - }, - "Microsoft.IdentityModel.Logging/8.14.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-eqqnemdW38CKZEHS6diA50BV94QICozDZEvSrsvN3SJXUFwVB9gy+/oz76gldP7nZliA16IglXjXTCTdmU/Ejg==", - "path": "microsoft.identitymodel.logging/8.14.0", - "hashPath": "microsoft.identitymodel.logging.8.14.0.nupkg.sha512" - }, - "Microsoft.IdentityModel.Tokens/8.14.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-lKIZiBiGd36k02TCdMHp1KlNWisyIvQxcYJvIkz7P4gSQ9zi8dgh6S5Grj8NNG7HWYIPfQymGyoZ6JB5d1Lo1g==", - "path": "microsoft.identitymodel.tokens/8.14.0", - "hashPath": "microsoft.identitymodel.tokens.8.14.0.nupkg.sha512" - }, - "NetEscapades.Configuration.Yaml/2.1.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-kNTX7kvRvbzBpLd3Vg9iu6t60tTyhVxsruAPgH6kl1GkAZIHLZw9cQysvjUenDU7JEnUgyxQnzfL8627ARDn+g==", - "path": "netescapades.configuration.yaml/2.1.0", - "hashPath": "netescapades.configuration.yaml.2.1.0.nupkg.sha512" - }, - "Pipelines.Sockets.Unofficial/2.2.8": { - "type": "package", - "serviceable": true, - "sha512": "sha512-zG2FApP5zxSx6OcdJQLbZDk2AVlN2BNQD6MorwIfV6gVj0RRxWPEp2LXAxqDGZqeNV1Zp0BNPcNaey/GXmTdvQ==", - "path": "pipelines.sockets.unofficial/2.2.8", - "hashPath": "pipelines.sockets.unofficial.2.2.8.nupkg.sha512" - }, - "Polly/7.2.4": { - "type": "package", - "serviceable": true, - "sha512": "sha512-bw00Ck5sh6ekduDE3mnCo1ohzuad946uslCDEENu3091+6UKnBuKLo4e+yaNcCzXxOZCXWY2gV4a35+K1d4LDA==", - "path": "polly/7.2.4", - "hashPath": "polly.7.2.4.nupkg.sha512" - }, - "Polly.Extensions.Http/3.0.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==", - "path": "polly.extensions.http/3.0.0", - "hashPath": "polly.extensions.http.3.0.0.nupkg.sha512" - }, - "SharpCompress/0.41.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==", - "path": "sharpcompress/0.41.0", - "hashPath": "sharpcompress.0.41.0.nupkg.sha512" - }, - "StackExchange.Redis/2.8.24": { - "type": "package", - "serviceable": true, - "sha512": "sha512-GWllmsFAtLyhm4C47cOCipGxyEi1NQWTFUHXnJ8hiHOsK/bH3T5eLkWPVW+LRL6jDiB3g3izW3YEHgLuPoJSyA==", - "path": "stackexchange.redis/2.8.24", - "hashPath": "stackexchange.redis.2.8.24.nupkg.sha512" - }, - "System.IdentityModel.Tokens.Jwt/7.2.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-Z3Fmkrxkp+o51ANMO/PqASRRlEz8dH4mTWwZXMFMXZt2bUGztBiNcIDnwBCElYLYpzpmz4sIqHb6aW8QVLe6YQ==", - "path": "system.identitymodel.tokens.jwt/7.2.0", - "hashPath": "system.identitymodel.tokens.jwt.7.2.0.nupkg.sha512" - }, - "YamlDotNet/9.1.0": { - "type": "package", - "serviceable": true, - "sha512": "sha512-fuvGXU4Ec5HrsmEc+BiFTNPCRf1cGBI2kh/3RzMWgddM2M4ALhbSPoI3X3mhXZUD1qqQd9oSkFAtWjpz8z9eRg==", - "path": "yamldotnet/9.1.0", - "hashPath": "yamldotnet.9.1.0.nupkg.sha512" - }, - "ZstdSharp.Port/0.8.6": { - "type": "package", - "serviceable": true, - "sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==", - "path": "zstdsharp.port/0.8.6", - "hashPath": "zstdsharp.port.0.8.6.nupkg.sha512" - }, - "StellaOps.Auth.Abstractions/1.0.0-preview.1": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Auth.Client/1.0.0-preview.1": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Auth.Security/1.0.0-preview.1": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Authority.Plugins.Abstractions/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Configuration/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Cryptography/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.DependencyInjection/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Plugin/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Scanner.Analyzers.Lang/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - }, - "StellaOps.Scanner.Core/1.0.0": { - "type": "project", - "serviceable": false, - "sha512": "" - } - } -} \ No newline at end of file diff --git a/out/linknotmerge-bench.csv b/out/linknotmerge-bench.csv deleted file mode 100644 index 7070a4e0..00000000 --- a/out/linknotmerge-bench.csv +++ /dev/null @@ -1,4 +0,0 @@ -scenario,iterations,observations,aliases,linksets,mean_total_ms,p95_total_ms,max_total_ms,mean_insert_ms,mean_correlation_ms,mean_throughput_per_sec,min_throughput_per_sec,mean_mongo_throughput_per_sec,min_mongo_throughput_per_sec,max_allocated_mb -lnm_ingest_baseline,5,5000,500,6000,555.1984,823.4957,866.6236,366.2635,188.9349,9877.7916,5769.5175,15338.0851,8405.1257,62.4477 -lnm_ingest_fanout_medium,5,10000,800,14800,785.8909,841.6247,842.8815,453.5087,332.3822,12794.9550,11864.0639,22086.0320,20891.0579,145.8328 -lnm_ingest_fanout_high,5,15000,1200,17400,1299.3458,1367.0934,1369.9430,741.6265,557.7193,11571.0991,10949.3607,20232.5180,19781.6762,238.3450 diff --git a/out/linknotmerge-bench.json b/out/linknotmerge-bench.json deleted file mode 100644 index cb8871e8..00000000 --- a/out/linknotmerge-bench.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "schemaVersion": "linknotmerge-bench/1.0", - "capturedAt": "2025-10-26T21:09:17.6345283+00:00", - "scenarios": [ - { - "id": "lnm_ingest_baseline", - "label": "5k observations, 500 aliases", - "iterations": 5, - "observations": 5000, - "aliases": 500, - "linksets": 6000, - "meanTotalMs": 555.1983600000001, - "p95TotalMs": 823.49568, - "maxTotalMs": 866.6236, - "meanInsertMs": 366.2635, - "meanCorrelationMs": 188.93486000000001, - "meanThroughputPerSecond": 9877.791561756272, - "minThroughputPerSecond": 5769.517469868118, - "meanMongoThroughputPerSecond": 15338.085148262326, - "minMongoThroughputPerSecond": 8405.1257146248, - "maxAllocatedMb": 62.44767761230469, - "thresholdMs": 900, - "minThroughputThresholdPerSecond": 5500, - "minMongoThroughputThresholdPerSecond": 8000, - "maxAllocatedThresholdMb": 160, - "regression": { - "limit": 1.15, - "breached": false - } - }, - { - "id": "lnm_ingest_fanout_medium", - "label": "10k observations, 800 aliases", - "iterations": 5, - "observations": 10000, - "aliases": 800, - "linksets": 14800, - "meanTotalMs": 785.89092, - "p95TotalMs": 841.6247, - "maxTotalMs": 842.8815, - "meanInsertMs": 453.50868, - "meanCorrelationMs": 332.38224, - "meanThroughputPerSecond": 12794.954951406156, - "minThroughputPerSecond": 11864.063928322072, - "meanMongoThroughputPerSecond": 22086.032034175576, - "minMongoThroughputPerSecond": 20891.057937797712, - "maxAllocatedMb": 145.83282470703125, - "thresholdMs": 1300, - "minThroughputThresholdPerSecond": 8000, - "minMongoThroughputThresholdPerSecond": 13000, - "maxAllocatedThresholdMb": 220, - "regression": { - "limit": 1.15, - "breached": false - } - }, - { - "id": "lnm_ingest_fanout_high", - "label": "15k observations, 1200 aliases", - "iterations": 5, - "observations": 15000, - "aliases": 1200, - "linksets": 17400, - "meanTotalMs": 1299.3458, - "p95TotalMs": 1367.09344, - "maxTotalMs": 1369.943, - "meanInsertMs": 741.62654, - "meanCorrelationMs": 557.71926, - "meanThroughputPerSecond": 11571.099129140825, - "minThroughputPerSecond": 10949.360666830664, - "meanMongoThroughputPerSecond": 20232.5179777937, - "minMongoThroughputPerSecond": 19781.676233305086, - "maxAllocatedMb": 238.34496307373047, - "thresholdMs": 2200, - "minThroughputThresholdPerSecond": 7000, - "minMongoThroughputThresholdPerSecond": 13000, - "maxAllocatedThresholdMb": 300, - "regression": { - "limit": 1.15, - "breached": false - } - } - ] -} \ No newline at end of file diff --git a/out/linknotmerge-bench.prom b/out/linknotmerge-bench.prom deleted file mode 100644 index 1f40b174..00000000 --- a/out/linknotmerge-bench.prom +++ /dev/null @@ -1,60 +0,0 @@ -# HELP linknotmerge_bench_total_ms Link-Not-Merge benchmark total duration metrics (milliseconds). -# TYPE linknotmerge_bench_total_ms gauge -# HELP linknotmerge_bench_correlation_ms Link-Not-Merge benchmark correlation duration metrics (milliseconds). -# TYPE linknotmerge_bench_correlation_ms gauge -# HELP linknotmerge_bench_insert_ms Link-Not-Merge benchmark Mongo insert duration metrics (milliseconds). -# TYPE linknotmerge_bench_insert_ms gauge -# HELP linknotmerge_bench_throughput_per_sec Link-Not-Merge benchmark throughput metrics (observations per second). -# TYPE linknotmerge_bench_throughput_per_sec gauge -# HELP linknotmerge_bench_mongo_throughput_per_sec Link-Not-Merge benchmark Mongo throughput metrics (operations per second). -# TYPE linknotmerge_bench_mongo_throughput_per_sec gauge -# HELP linknotmerge_bench_allocated_mb Link-Not-Merge benchmark allocation metrics (megabytes). -# TYPE linknotmerge_bench_allocated_mb gauge -linknotmerge_bench_mean_total_ms{scenario="lnm_ingest_baseline"} 555.19836000000009 -linknotmerge_bench_p95_total_ms{scenario="lnm_ingest_baseline"} 823.49567999999999 -linknotmerge_bench_max_total_ms{scenario="lnm_ingest_baseline"} 866.62360000000001 -linknotmerge_bench_threshold_ms{scenario="lnm_ingest_baseline"} 900 -linknotmerge_bench_mean_correlation_ms{scenario="lnm_ingest_baseline"} 188.93486000000001 -linknotmerge_bench_mean_insert_ms{scenario="lnm_ingest_baseline"} 366.26350000000002 -linknotmerge_bench_mean_throughput_per_sec{scenario="lnm_ingest_baseline"} 9877.7915617562721 -linknotmerge_bench_min_throughput_per_sec{scenario="lnm_ingest_baseline"} 5769.5174698681176 -linknotmerge_bench_throughput_floor_per_sec{scenario="lnm_ingest_baseline"} 5500 -linknotmerge_bench_mean_mongo_throughput_per_sec{scenario="lnm_ingest_baseline"} 15338.085148262326 -linknotmerge_bench_min_mongo_throughput_per_sec{scenario="lnm_ingest_baseline"} 8405.1257146248008 -linknotmerge_bench_mongo_throughput_floor_per_sec{scenario="lnm_ingest_baseline"} 8000 -linknotmerge_bench_max_allocated_mb{scenario="lnm_ingest_baseline"} 62.447677612304688 -linknotmerge_bench_max_allocated_threshold_mb{scenario="lnm_ingest_baseline"} 160 -linknotmerge_bench_regression_limit{scenario="lnm_ingest_baseline"} 1.1499999999999999 -linknotmerge_bench_regression_breached{scenario="lnm_ingest_baseline"} 0 -linknotmerge_bench_mean_total_ms{scenario="lnm_ingest_fanout_medium"} 785.89092000000005 -linknotmerge_bench_p95_total_ms{scenario="lnm_ingest_fanout_medium"} 841.62469999999996 -linknotmerge_bench_max_total_ms{scenario="lnm_ingest_fanout_medium"} 842.88149999999996 -linknotmerge_bench_threshold_ms{scenario="lnm_ingest_fanout_medium"} 1300 -linknotmerge_bench_mean_correlation_ms{scenario="lnm_ingest_fanout_medium"} 332.38224000000002 -linknotmerge_bench_mean_insert_ms{scenario="lnm_ingest_fanout_medium"} 453.50868000000003 -linknotmerge_bench_mean_throughput_per_sec{scenario="lnm_ingest_fanout_medium"} 12794.954951406156 -linknotmerge_bench_min_throughput_per_sec{scenario="lnm_ingest_fanout_medium"} 11864.063928322072 -linknotmerge_bench_throughput_floor_per_sec{scenario="lnm_ingest_fanout_medium"} 8000 -linknotmerge_bench_mean_mongo_throughput_per_sec{scenario="lnm_ingest_fanout_medium"} 22086.032034175576 -linknotmerge_bench_min_mongo_throughput_per_sec{scenario="lnm_ingest_fanout_medium"} 20891.057937797712 -linknotmerge_bench_mongo_throughput_floor_per_sec{scenario="lnm_ingest_fanout_medium"} 13000 -linknotmerge_bench_max_allocated_mb{scenario="lnm_ingest_fanout_medium"} 145.83282470703125 -linknotmerge_bench_max_allocated_threshold_mb{scenario="lnm_ingest_fanout_medium"} 220 -linknotmerge_bench_regression_limit{scenario="lnm_ingest_fanout_medium"} 1.1499999999999999 -linknotmerge_bench_regression_breached{scenario="lnm_ingest_fanout_medium"} 0 -linknotmerge_bench_mean_total_ms{scenario="lnm_ingest_fanout_high"} 1299.3458000000001 -linknotmerge_bench_p95_total_ms{scenario="lnm_ingest_fanout_high"} 1367.0934400000001 -linknotmerge_bench_max_total_ms{scenario="lnm_ingest_fanout_high"} 1369.943 -linknotmerge_bench_threshold_ms{scenario="lnm_ingest_fanout_high"} 2200 -linknotmerge_bench_mean_correlation_ms{scenario="lnm_ingest_fanout_high"} 557.71925999999996 -linknotmerge_bench_mean_insert_ms{scenario="lnm_ingest_fanout_high"} 741.62653999999998 -linknotmerge_bench_mean_throughput_per_sec{scenario="lnm_ingest_fanout_high"} 11571.099129140825 -linknotmerge_bench_min_throughput_per_sec{scenario="lnm_ingest_fanout_high"} 10949.360666830664 -linknotmerge_bench_throughput_floor_per_sec{scenario="lnm_ingest_fanout_high"} 7000 -linknotmerge_bench_mean_mongo_throughput_per_sec{scenario="lnm_ingest_fanout_high"} 20232.517977793701 -linknotmerge_bench_min_mongo_throughput_per_sec{scenario="lnm_ingest_fanout_high"} 19781.676233305086 -linknotmerge_bench_mongo_throughput_floor_per_sec{scenario="lnm_ingest_fanout_high"} 13000 -linknotmerge_bench_max_allocated_mb{scenario="lnm_ingest_fanout_high"} 238.34496307373047 -linknotmerge_bench_max_allocated_threshold_mb{scenario="lnm_ingest_fanout_high"} 300 -linknotmerge_bench_regression_limit{scenario="lnm_ingest_fanout_high"} 1.1499999999999999 -linknotmerge_bench_regression_breached{scenario="lnm_ingest_fanout_high"} 0 diff --git a/out/linknotmerge-vex-bench.csv b/out/linknotmerge-vex-bench.csv deleted file mode 100644 index b78eeb39..00000000 --- a/out/linknotmerge-vex-bench.csv +++ /dev/null @@ -1,4 +0,0 @@ -scenario,iterations,observations,statements,events,mean_total_ms,p95_total_ms,max_total_ms,mean_insert_ms,mean_correlation_ms,mean_observation_throughput_per_sec,min_observation_throughput_per_sec,mean_event_throughput_per_sec,min_event_throughput_per_sec,max_allocated_mb -vex_ingest_baseline,5,4000,24000,21326,842.8191,1319.3038,1432.7675,346.7277,496.0915,5349.8940,2791.7998,48942.4901,24653.0556,138.6365 -vex_ingest_medium,5,8000,64000,56720,1525.9929,1706.8900,1748.9056,533.3378,992.6552,5274.5883,4574.2892,57654.9190,48531.7353,326.8638 -vex_ingest_high,5,12000,120000,106910,2988.5094,3422.1728,3438.9364,903.3927,2085.1167,4066.2300,3489.4510,52456.9493,42358.0556,583.9903 diff --git a/out/linknotmerge-vex-bench.json b/out/linknotmerge-vex-bench.json deleted file mode 100644 index 439275b6..00000000 --- a/out/linknotmerge-vex-bench.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "schemaVersion": "linknotmerge-vex-bench/1.0", - "capturedAt": "2025-10-26T21:29:34.4007212+00:00", - "scenarios": [ - { - "id": "vex_ingest_baseline", - "label": "4k observations, 400 aliases", - "iterations": 5, - "observations": 4000, - "statements": 24000, - "events": 21326, - "meanTotalMs": 842.81914, - "p95TotalMs": 1319.3037799999997, - "maxTotalMs": 1432.7675, - "meanInsertMs": 346.72766, - "meanCorrelationMs": 496.09147999999993, - "meanObservationThroughputPerSecond": 5349.894040882909, - "minObservationThroughputPerSecond": 2791.7997860783416, - "meanEventThroughputPerSecond": 48942.49008943273, - "minEventThroughputPerSecond": 24653.055581276763, - "maxAllocatedMb": 138.63648986816406, - "thresholdMs": 2300, - "minObservationThroughputThresholdPerSecond": 1800, - "minEventThroughputThresholdPerSecond": 2000, - "maxAllocatedThresholdMb": 220, - "regression": { - "limit": 1.15, - "breached": false - } - }, - { - "id": "vex_ingest_medium", - "label": "8k observations, 700 aliases", - "iterations": 5, - "observations": 8000, - "statements": 64000, - "events": 56720, - "meanTotalMs": 1525.99294, - "p95TotalMs": 1706.89, - "maxTotalMs": 1748.9056, - "meanInsertMs": 533.3377800000001, - "meanCorrelationMs": 992.6551599999999, - "meanObservationThroughputPerSecond": 5274.588273225903, - "minObservationThroughputPerSecond": 4574.289201201025, - "meanEventThroughputPerSecond": 57654.91903920916, - "minEventThroughputPerSecond": 48531.73532270095, - "maxAllocatedMb": 326.8638000488281, - "thresholdMs": 3200, - "minObservationThroughputThresholdPerSecond": 2200, - "minEventThroughputThresholdPerSecond": 2500, - "maxAllocatedThresholdMb": 400, - "regression": { - "limit": 1.15, - "breached": false - } - }, - { - "id": "vex_ingest_high", - "label": "12k observations, 1100 aliases", - "iterations": 5, - "observations": 12000, - "statements": 120000, - "events": 106910, - "meanTotalMs": 2988.50936, - "p95TotalMs": 3422.1728, - "maxTotalMs": 3438.9364, - "meanInsertMs": 903.3926800000002, - "meanCorrelationMs": 2085.11668, - "meanObservationThroughputPerSecond": 4066.2299506870645, - "minObservationThroughputPerSecond": 3489.450982577055, - "meanEventThroughputPerSecond": 52456.94928323016, - "minEventThroughputPerSecond": 42358.05564361166, - "maxAllocatedMb": 583.9903411865234, - "thresholdMs": 4200, - "minObservationThroughputThresholdPerSecond": 2200, - "minEventThroughputThresholdPerSecond": 2500, - "maxAllocatedThresholdMb": 700, - "regression": { - "limit": 1.15, - "breached": false - } - } - ] -} \ No newline at end of file diff --git a/out/linknotmerge-vex-bench.prom b/out/linknotmerge-vex-bench.prom deleted file mode 100644 index 08cd3d88..00000000 --- a/out/linknotmerge-vex-bench.prom +++ /dev/null @@ -1,50 +0,0 @@ -# HELP linknotmerge_vex_bench_total_ms Link-Not-Merge VEX benchmark total duration (milliseconds). -# TYPE linknotmerge_vex_bench_total_ms gauge -# HELP linknotmerge_vex_bench_throughput_per_sec Link-Not-Merge VEX benchmark observation throughput (observations per second). -# TYPE linknotmerge_vex_bench_throughput_per_sec gauge -# HELP linknotmerge_vex_bench_event_throughput_per_sec Link-Not-Merge VEX benchmark event throughput (events per second). -# TYPE linknotmerge_vex_bench_event_throughput_per_sec gauge -# HELP linknotmerge_vex_bench_allocated_mb Link-Not-Merge VEX benchmark max allocations (megabytes). -# TYPE linknotmerge_vex_bench_allocated_mb gauge -linknotmerge_vex_bench_mean_total_ms{scenario="vex_ingest_baseline"} 842.81913999999995 -linknotmerge_vex_bench_p95_total_ms{scenario="vex_ingest_baseline"} 1319.3037799999997 -linknotmerge_vex_bench_max_total_ms{scenario="vex_ingest_baseline"} 1432.7674999999999 -linknotmerge_vex_bench_threshold_ms{scenario="vex_ingest_baseline"} 2300 -linknotmerge_vex_bench_mean_observation_throughput_per_sec{scenario="vex_ingest_baseline"} 5349.8940408829094 -linknotmerge_vex_bench_min_observation_throughput_per_sec{scenario="vex_ingest_baseline"} 2791.7997860783416 -linknotmerge_vex_bench_observation_throughput_floor_per_sec{scenario="vex_ingest_baseline"} 1800 -linknotmerge_vex_bench_mean_event_throughput_per_sec{scenario="vex_ingest_baseline"} 48942.490089432729 -linknotmerge_vex_bench_min_event_throughput_per_sec{scenario="vex_ingest_baseline"} 24653.055581276763 -linknotmerge_vex_bench_event_throughput_floor_per_sec{scenario="vex_ingest_baseline"} 2000 -linknotmerge_vex_bench_max_allocated_mb{scenario="vex_ingest_baseline"} 138.63648986816406 -linknotmerge_vex_bench_max_allocated_threshold_mb{scenario="vex_ingest_baseline"} 220 -linknotmerge_vex_bench_regression_limit{scenario="vex_ingest_baseline"} 1.1499999999999999 -linknotmerge_vex_bench_regression_breached{scenario="vex_ingest_baseline"} 0 -linknotmerge_vex_bench_mean_total_ms{scenario="vex_ingest_medium"} 1525.9929400000001 -linknotmerge_vex_bench_p95_total_ms{scenario="vex_ingest_medium"} 1706.8900000000001 -linknotmerge_vex_bench_max_total_ms{scenario="vex_ingest_medium"} 1748.9056 -linknotmerge_vex_bench_threshold_ms{scenario="vex_ingest_medium"} 3200 -linknotmerge_vex_bench_mean_observation_throughput_per_sec{scenario="vex_ingest_medium"} 5274.5882732259033 -linknotmerge_vex_bench_min_observation_throughput_per_sec{scenario="vex_ingest_medium"} 4574.2892012010252 -linknotmerge_vex_bench_observation_throughput_floor_per_sec{scenario="vex_ingest_medium"} 2200 -linknotmerge_vex_bench_mean_event_throughput_per_sec{scenario="vex_ingest_medium"} 57654.919039209162 -linknotmerge_vex_bench_min_event_throughput_per_sec{scenario="vex_ingest_medium"} 48531.735322700952 -linknotmerge_vex_bench_event_throughput_floor_per_sec{scenario="vex_ingest_medium"} 2500 -linknotmerge_vex_bench_max_allocated_mb{scenario="vex_ingest_medium"} 326.86380004882812 -linknotmerge_vex_bench_max_allocated_threshold_mb{scenario="vex_ingest_medium"} 400 -linknotmerge_vex_bench_regression_limit{scenario="vex_ingest_medium"} 1.1499999999999999 -linknotmerge_vex_bench_regression_breached{scenario="vex_ingest_medium"} 0 -linknotmerge_vex_bench_mean_total_ms{scenario="vex_ingest_high"} 2988.50936 -linknotmerge_vex_bench_p95_total_ms{scenario="vex_ingest_high"} 3422.1727999999998 -linknotmerge_vex_bench_max_total_ms{scenario="vex_ingest_high"} 3438.9364 -linknotmerge_vex_bench_threshold_ms{scenario="vex_ingest_high"} 4200 -linknotmerge_vex_bench_mean_observation_throughput_per_sec{scenario="vex_ingest_high"} 4066.2299506870645 -linknotmerge_vex_bench_min_observation_throughput_per_sec{scenario="vex_ingest_high"} 3489.4509825770551 -linknotmerge_vex_bench_observation_throughput_floor_per_sec{scenario="vex_ingest_high"} 2200 -linknotmerge_vex_bench_mean_event_throughput_per_sec{scenario="vex_ingest_high"} 52456.949283230162 -linknotmerge_vex_bench_min_event_throughput_per_sec{scenario="vex_ingest_high"} 42358.05564361166 -linknotmerge_vex_bench_event_throughput_floor_per_sec{scenario="vex_ingest_high"} 2500 -linknotmerge_vex_bench_max_allocated_mb{scenario="vex_ingest_high"} 583.99034118652344 -linknotmerge_vex_bench_max_allocated_threshold_mb{scenario="vex_ingest_high"} 700 -linknotmerge_vex_bench_regression_limit{scenario="vex_ingest_high"} 1.1499999999999999 -linknotmerge_vex_bench_regression_breached{scenario="vex_ingest_high"} 0 diff --git a/out/notify-bench.csv b/out/notify-bench.csv deleted file mode 100644 index 0030cde3..00000000 --- a/out/notify-bench.csv +++ /dev/null @@ -1,4 +0,0 @@ -scenario,iterations,events,deliveries,mean_ms,p95_ms,max_ms,mean_throughput_per_sec,min_throughput_per_sec,max_allocated_mb -notify_dispatch_density_05,5,5000,20000,3.4150,4.1722,4.3039,6053938.5172,4646948.1168,0.0000 -notify_dispatch_density_20,5,7500,675000,24.2274,25.8517,26.0526,27923335.5855,25909122.3141,0.0000 -notify_dispatch_density_40,5,10000,4000080,138.7387,147.7174,149.1124,28916602.9214,26825938.0172,0.0000 diff --git a/out/notify-bench.json b/out/notify-bench.json deleted file mode 100644 index 8c3e075d..00000000 --- a/out/notify-bench.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "schemaVersion": "notify-dispatch-bench/1.0", - "capturedAt": "2025-10-26T20:28:56.3603045+00:00", - "scenarios": [ - { - "id": "notify_dispatch_density_05", - "label": "50 rules / 5% fanout", - "iterations": 5, - "totalEvents": 5000, - "totalRules": 50, - "actionsPerRule": 2, - "averageMatchesPerEvent": 2, - "minMatchesPerEvent": 2, - "maxMatchesPerEvent": 2, - "averageDeliveriesPerEvent": 4, - "totalDeliveries": 20000, - "meanMs": 3.41498, - "p95Ms": 4.17216, - "maxMs": 4.3039, - "meanThroughputPerSecond": 6053938.51717893, - "minThroughputPerSecond": 4646948.116824276, - "maxAllocatedMb": 0, - "thresholdMs": 400, - "minThroughputThresholdPerSecond": 15000, - "maxAllocatedThresholdMb": 128, - "regression": { - "limit": 1.15, - "breached": false - } - }, - { - "id": "notify_dispatch_density_20", - "label": "150 rules / 20% fanout", - "iterations": 5, - "totalEvents": 7500, - "totalRules": 150, - "actionsPerRule": 3, - "averageMatchesPerEvent": 30, - "minMatchesPerEvent": 30, - "maxMatchesPerEvent": 30, - "averageDeliveriesPerEvent": 90, - "totalDeliveries": 675000, - "meanMs": 24.2274, - "p95Ms": 25.85172, - "maxMs": 26.0526, - "meanThroughputPerSecond": 27923335.585545264, - "minThroughputPerSecond": 25909122.314087655, - "maxAllocatedMb": 0, - "thresholdMs": 650, - "minThroughputThresholdPerSecond": 30000, - "maxAllocatedThresholdMb": 192, - "regression": { - "limit": 1.15, - "breached": false - } - }, - { - "id": "notify_dispatch_density_40", - "label": "300 rules / 40% fanout", - "iterations": 5, - "totalEvents": 10000, - "totalRules": 300, - "actionsPerRule": 4, - "averageMatchesPerEvent": 100.002, - "minMatchesPerEvent": 60, - "maxMatchesPerEvent": 120, - "averageDeliveriesPerEvent": 400.008, - "totalDeliveries": 4000080, - "meanMs": 138.73866, - "p95Ms": 147.71738000000002, - "maxMs": 149.1124, - "meanThroughputPerSecond": 28916602.921385907, - "minThroughputPerSecond": 26825938.017227273, - "maxAllocatedMb": 0, - "thresholdMs": 900, - "minThroughputThresholdPerSecond": 45000, - "maxAllocatedThresholdMb": 256, - "regression": { - "limit": 1.15, - "breached": false - } - } - ] -} \ No newline at end of file diff --git a/out/notify-bench.prom b/out/notify-bench.prom deleted file mode 100644 index e7ebe961..00000000 --- a/out/notify-bench.prom +++ /dev/null @@ -1,39 +0,0 @@ -# HELP notify_dispatch_bench_duration_ms Notify dispatch benchmark duration metrics (milliseconds). -# TYPE notify_dispatch_bench_duration_ms gauge -# HELP notify_dispatch_bench_throughput_per_sec Notify dispatch benchmark throughput metrics (deliveries per second). -# TYPE notify_dispatch_bench_throughput_per_sec gauge -# HELP notify_dispatch_bench_allocation_mb Notify dispatch benchmark allocation metrics (megabytes). -# TYPE notify_dispatch_bench_allocation_mb gauge -notify_dispatch_bench_mean_ms{scenario="notify_dispatch_density_05"} 3.4149799999999999 -notify_dispatch_bench_p95_ms{scenario="notify_dispatch_density_05"} 4.1721599999999999 -notify_dispatch_bench_max_ms{scenario="notify_dispatch_density_05"} 4.3038999999999996 -notify_dispatch_bench_threshold_ms{scenario="notify_dispatch_density_05"} 400 -notify_dispatch_bench_mean_throughput_per_sec{scenario="notify_dispatch_density_05"} 6053938.5171789303 -notify_dispatch_bench_min_throughput_per_sec{scenario="notify_dispatch_density_05"} 4646948.1168242758 -notify_dispatch_bench_min_throughput_threshold_per_sec{scenario="notify_dispatch_density_05"} 15000 -notify_dispatch_bench_max_allocated_mb{scenario="notify_dispatch_density_05"} 0 -notify_dispatch_bench_max_allocated_threshold_mb{scenario="notify_dispatch_density_05"} 128 -notify_dispatch_bench_regression_limit{scenario="notify_dispatch_density_05"} 1.1499999999999999 -notify_dispatch_bench_regression_breached{scenario="notify_dispatch_density_05"} 0 -notify_dispatch_bench_mean_ms{scenario="notify_dispatch_density_20"} 24.227399999999999 -notify_dispatch_bench_p95_ms{scenario="notify_dispatch_density_20"} 25.85172 -notify_dispatch_bench_max_ms{scenario="notify_dispatch_density_20"} 26.052600000000002 -notify_dispatch_bench_threshold_ms{scenario="notify_dispatch_density_20"} 650 -notify_dispatch_bench_mean_throughput_per_sec{scenario="notify_dispatch_density_20"} 27923335.585545264 -notify_dispatch_bench_min_throughput_per_sec{scenario="notify_dispatch_density_20"} 25909122.314087655 -notify_dispatch_bench_min_throughput_threshold_per_sec{scenario="notify_dispatch_density_20"} 30000 -notify_dispatch_bench_max_allocated_mb{scenario="notify_dispatch_density_20"} 0 -notify_dispatch_bench_max_allocated_threshold_mb{scenario="notify_dispatch_density_20"} 192 -notify_dispatch_bench_regression_limit{scenario="notify_dispatch_density_20"} 1.1499999999999999 -notify_dispatch_bench_regression_breached{scenario="notify_dispatch_density_20"} 0 -notify_dispatch_bench_mean_ms{scenario="notify_dispatch_density_40"} 138.73866000000001 -notify_dispatch_bench_p95_ms{scenario="notify_dispatch_density_40"} 147.71738000000002 -notify_dispatch_bench_max_ms{scenario="notify_dispatch_density_40"} 149.11240000000001 -notify_dispatch_bench_threshold_ms{scenario="notify_dispatch_density_40"} 900 -notify_dispatch_bench_mean_throughput_per_sec{scenario="notify_dispatch_density_40"} 28916602.921385907 -notify_dispatch_bench_min_throughput_per_sec{scenario="notify_dispatch_density_40"} 26825938.017227273 -notify_dispatch_bench_min_throughput_threshold_per_sec{scenario="notify_dispatch_density_40"} 45000 -notify_dispatch_bench_max_allocated_mb{scenario="notify_dispatch_density_40"} 0 -notify_dispatch_bench_max_allocated_threshold_mb{scenario="notify_dispatch_density_40"} 256 -notify_dispatch_bench_regression_limit{scenario="notify_dispatch_density_40"} 1.1499999999999999 -notify_dispatch_bench_regression_breached{scenario="notify_dispatch_density_40"} 0 diff --git a/out/policy-bench.csv b/out/policy-bench.csv deleted file mode 100644 index b5be42ff..00000000 --- a/out/policy-bench.csv +++ /dev/null @@ -1,2 +0,0 @@ -scenario,iterations,findings,mean_ms,p95_ms,max_ms,mean_throughput_per_sec,min_throughput_per_sec,max_allocated_mb -policy_eval_baseline,3,1000000,1109.3542,1257.7493,1280.1721,912094.5581,781144.9726,563.6901 diff --git a/out/policy-bench.json b/out/policy-bench.json deleted file mode 100644 index 30c8f568..00000000 --- a/out/policy-bench.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "schemaVersion": "policy-bench/1.0", - "capturedAt": "2025-10-26T19:57:27.4363234+00:00", - "scenarios": [ - { - "id": "policy_eval_baseline", - "label": "Policy evaluation (100k components, 1M findings)", - "iterations": 3, - "findingCount": 1000000, - "meanMs": 1109.3542333333335, - "p95Ms": 1257.74929, - "maxMs": 1280.1721, - "meanThroughputPerSecond": 912094.5580512757, - "minThroughputPerSecond": 781144.9726173537, - "maxAllocatedMb": 563.6900634765625, - "thresholdMs": 20000, - "minThroughputThresholdPerSecond": 60000, - "maxAllocatedThresholdMb": 900, - "regression": { - "limit": 1.15, - "breached": false - } - } - ] -} \ No newline at end of file diff --git a/out/policy-bench.prom b/out/policy-bench.prom deleted file mode 100644 index 4ee76ee8..00000000 --- a/out/policy-bench.prom +++ /dev/null @@ -1,17 +0,0 @@ -# HELP policy_engine_bench_duration_ms Policy Engine benchmark duration metrics (milliseconds). -# TYPE policy_engine_bench_duration_ms gauge -# HELP policy_engine_bench_throughput_per_sec Policy Engine benchmark throughput metrics (findings per second). -# TYPE policy_engine_bench_throughput_per_sec gauge -# HELP policy_engine_bench_allocation_mb Policy Engine benchmark allocation metrics (megabytes). -# TYPE policy_engine_bench_allocation_mb gauge -policy_engine_bench_mean_ms{scenario="policy_eval_baseline"} 1109.3542333333335 -policy_engine_bench_p95_ms{scenario="policy_eval_baseline"} 1257.74929 -policy_engine_bench_max_ms{scenario="policy_eval_baseline"} 1280.1721 -policy_engine_bench_threshold_ms{scenario="policy_eval_baseline"} 20000 -policy_engine_bench_mean_throughput_per_sec{scenario="policy_eval_baseline"} 912094.55805127567 -policy_engine_bench_min_throughput_per_sec{scenario="policy_eval_baseline"} 781144.97261735366 -policy_engine_bench_min_throughput_threshold_per_sec{scenario="policy_eval_baseline"} 60000 -policy_engine_bench_max_allocated_mb{scenario="policy_eval_baseline"} 563.6900634765625 -policy_engine_bench_max_allocated_threshold_mb{scenario="policy_eval_baseline"} 900 -policy_engine_bench_regression_limit{scenario="policy_eval_baseline"} 1.1499999999999999 -policy_engine_bench_regression_breached{scenario="policy_eval_baseline"} 0 diff --git a/out/policy-simulations/policy-simulation-summary.json b/out/policy-simulations/policy-simulation-summary.json deleted file mode 100644 index 53a2ce58..00000000 --- a/out/policy-simulations/policy-simulation-summary.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "ScenarioName": "baseline", - "Success": true, - "ChangedCount": 2, - "Failures": [], - "ActualStatuses": { - "library:pkg/openssl@1.1.1w": "Blocked", - "library:pkg/internal-runtime@1.0.0": "Warned" - } - }, - { - "ScenarioName": "internal-only", - "Success": true, - "ChangedCount": 2, - "Failures": [], - "ActualStatuses": { - "library:pkg/internal-app@2.0.0": "RequiresVex", - "library:pkg/kev-component@3.1.4": "RequiresVex" - } - }, - { - "ScenarioName": "serverless", - "Success": true, - "ChangedCount": 2, - "Failures": [], - "ActualStatuses": { - "library:pkg/aws-lambda@1.0.0": "Blocked", - "image:sha256:untrusted-base": "Blocked" - } - } -] \ No newline at end of file diff --git a/out/tmp-cdx/Program.cs b/out/tmp-cdx/Program.cs deleted file mode 100644 index 2a5e0526..00000000 --- a/out/tmp-cdx/Program.cs +++ /dev/null @@ -1,4 +0,0 @@ -using System; -using CycloneDX.Models; - -Console.WriteLine(string.Join(", ", Enum.GetNames(typeof(Component.Classification)))); diff --git a/out/tmp-cdx/tmp-cdx.csproj b/out/tmp-cdx/tmp-cdx.csproj deleted file mode 100644 index 6b239424..00000000 --- a/out/tmp-cdx/tmp-cdx.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - net10.0 - tmp_cdx - enable - enable - - - - - - - diff --git a/plugins/cli/StellaOps.Cli.Plugins.NonCore/manifest.json b/plugins/cli/StellaOps.Cli.Plugins.NonCore/manifest.json deleted file mode 100644 index 455bd987..00000000 --- a/plugins/cli/StellaOps.Cli.Plugins.NonCore/manifest.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "schemaVersion": "1.0", - "id": "stellaops.cli.plugins.noncore", - "displayName": "StellaOps CLI Non-core Verbs", - "version": "0.1.0", - "requiresRestart": true, - "entryPoint": { - "type": "dotnet", - "assembly": "StellaOps.Cli.Plugins.NonCore.dll", - "typeName": "StellaOps.Cli.Plugins.NonCore.NonCoreCliCommandModule" - }, - "capabilities": [ - "cli", - "excititor", - "runtime-policy", - "offline-kit" - ], - "metadata": { - "org.stellaops.restart.required": "true" - } -} diff --git a/samples/policy/README.md b/samples/policy/README.md index e1cbcb7e..3e47f952 100644 --- a/samples/policy/README.md +++ b/samples/policy/README.md @@ -12,7 +12,7 @@ Run the simulation harness locally: ```bash dotnet run \ - --project tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj \ + --project src/Tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj \ -- \ --scenario-root samples/policy/simulations \ --output out/policy-simulations diff --git a/scripts/export-policy-schemas.sh b/scripts/export-policy-schemas.sh index 13dc1d1a..4f7c1ea8 100644 --- a/scripts/export-policy-schemas.sh +++ b/scripts/export-policy-schemas.sh @@ -6,6 +6,6 @@ OUTPUT_DIR="${1:-$REPO_ROOT/docs/schemas}" pushd "$REPO_ROOT" > /dev/null -dotnet run --project tools/PolicySchemaExporter -- "$OUTPUT_DIR" +dotnet run --project src/Tools/PolicySchemaExporter -- "$OUTPUT_DIR" popd > /dev/null diff --git a/seed-data/cert-bund/README.md b/seed-data/cert-bund/README.md index c31fea90..59c379ee 100644 --- a/seed-data/cert-bund/README.md +++ b/seed-data/cert-bund/README.md @@ -32,15 +32,15 @@ the tooling described below. ## Tooling -Run the helper under `tools/` to capture fresh snapshots or regenerate +Run the helper under `src/Tools/` to capture fresh snapshots or regenerate the manifest: ``` -python tools/certbund_offline_snapshot.py --output seed-data/cert-bund +python src/Tools/certbund_offline_snapshot.py --output seed-data/cert-bund ``` See the connector operations guide -(`docs/ops/concelier-certbund-operations.md`) for detailed usage, +(`docs/modules/concelier/operations/connectors/certbund.md`) for detailed usage, including how to provide cookies/tokens when the portal requires manual authentication. diff --git a/src/Attestor/StellaOps.Attestor.Types/TASKS.md b/src/Attestor/StellaOps.Attestor.Types/TASKS.md index d2eb61f3..76e69812 100644 --- a/src/Attestor/StellaOps.Attestor.Types/TASKS.md +++ b/src/Attestor/StellaOps.Attestor.Types/TASKS.md @@ -10,4 +10,4 @@ | ID | Status | Owner(s) | Depends on | Description | Exit Criteria | |----|--------|----------|------------|-------------|---------------| | ATTEST-TYPES-73-001 | TODO | Attestation Payloads Guild | ATTEST-TYPES-72-002 | Create golden payload samples for each type; integrate into tests and documentation. | Golden fixtures stored; tests compare outputs; docs embed examples. | -| ATTEST-TYPES-73-002 | TODO | Attestation Payloads Guild, Docs Guild | ATTEST-TYPES-73-001 | Publish schema reference docs (`/docs/attestor/payloads.md`) with annotated JSON examples. | Doc merged with banner; examples validated by tests. | +| ATTEST-TYPES-73-002 | TODO | Attestation Payloads Guild, Docs Guild | ATTEST-TYPES-73-001 | Publish schema reference docs (`/docs/modules/attestor/payloads.md`) with annotated JSON examples. | Doc merged with banner; examples validated by tests. | diff --git a/src/Attestor/StellaOps.Attestor.Verify/TASKS.md b/src/Attestor/StellaOps.Attestor.Verify/TASKS.md index f4c3c5cf..5fc5af25 100644 --- a/src/Attestor/StellaOps.Attestor.Verify/TASKS.md +++ b/src/Attestor/StellaOps.Attestor.Verify/TASKS.md @@ -10,4 +10,4 @@ | ID | Status | Owner(s) | Depends on | Description | Exit Criteria | |----|--------|----------|------------|-------------|---------------| | ATTEST-VERIFY-74-001 | TODO | Verification Guild, Observability Guild | ATTEST-VERIFY-73-001 | Emit telemetry (spans/metrics) tagged by subject, issuer, policy, result; integrate with dashboards. | Metrics visible; spans present; SLO thresholds defined. | -| ATTEST-VERIFY-74-002 | TODO | Verification Guild, Docs Guild | ATTEST-VERIFY-73-001 | Document verification report schema and explainability in `/docs/attestor/workflows.md`. | Documentation merged; examples verified via tests. | +| ATTEST-VERIFY-74-002 | TODO | Verification Guild, Docs Guild | ATTEST-VERIFY-73-001 | Document verification report schema and explainability in `/docs/modules/attestor/workflows.md`. | Documentation merged; examples verified via tests. | diff --git a/src/Cli/StellaOps.Cli/AGENTS.md b/src/Cli/StellaOps.Cli/AGENTS.md index 4e504f0a..013b48ab 100644 --- a/src/Cli/StellaOps.Cli/AGENTS.md +++ b/src/Cli/StellaOps.Cli/AGENTS.md @@ -21,7 +21,7 @@ - Update `TASKS.md` as states change (TODO → DOING → DONE/BLOCKED) and record added tests/fixtures alongside implementation notes. ## Reference Materials -- `docs/ARCHITECTURE_CONCELIER.md` for database operations surface area. +- `docs/modules/concelier/ARCHITECTURE.md` for database operations surface area. - Backend OpenAPI/contract docs (once available) for job triggers and scanner endpoints. - Existing module AGENTS/TASKS files for style and coordination cues. - `docs/09_API_CLI_REFERENCE.md` (section 3) for the user-facing synopsis of the CLI verbs and flags. diff --git a/src/Cli/StellaOps.Cli/TASKS.md b/src/Cli/StellaOps.Cli/TASKS.md index 17254882..9d68fcc3 100644 --- a/src/Cli/StellaOps.Cli/TASKS.md +++ b/src/Cli/StellaOps.Cli/TASKS.md @@ -2,7 +2,7 @@ | ID | Status | Owner(s) | Depends on | Description | Exit Criteria | |----|--------|----------|------------|-------------|---------------| | CLI-AOC-19-001 | DONE (2025-10-27) | DevEx/CLI Guild | CONCELIER-WEB-AOC-19-001, EXCITITOR-WEB-AOC-19-001 | Implement `stella sources ingest --dry-run` printing would-write payloads with forbidden field scan results and guard status. | Command displays diff-safe JSON, highlights forbidden fields, exits non-zero on guard violation, and has unit tests. | -> Docs ready (2025-10-26): Reference behaviour/spec in `docs/cli/cli-reference.md` §2 and AOC reference §5. +> Docs ready (2025-10-26): Reference behaviour/spec in `docs/modules/cli/guides/cli-reference.md` §2 and AOC reference §5. > 2025-10-27: CLI command scaffolded with backend client call, JSON/table output, gzip/base64 normalisation, and exit-code mapping. Awaiting Concelier dry-run endpoint + integration tests once backend lands. > 2025-10-27: Progress paused before adding CLI unit tests; blocked on extending `StubBackendClient` + fixtures for `ExecuteAocIngestDryRunAsync` coverage. > 2025-10-27: Added stubbed ingest responses + unit tests covering success/violation paths, output writing, and exit-code mapping. @@ -11,7 +11,7 @@ > 2025-10-27: CLI wiring in progress; backend client/command surface being added with table/JSON output. > 2025-10-27: Added JSON/table Spectre output, integration tests for exit-code handling, CLI metrics, and updated quickstart/architecture docs to cover guard workflows. | CLI-AOC-19-003 | DONE (2025-10-27) | Docs/CLI Guild | CLI-AOC-19-001, CLI-AOC-19-002 | Update CLI reference and quickstart docs to cover new commands, exit codes, and offline verification workflows. | Docs updated; examples recorded; release notes mention new commands. | -> Docs note (2025-10-26): `docs/cli/cli-reference.md` now describes both commands, exit codes, and offline usage—sync help text once implementation lands. +> Docs note (2025-10-26): `docs/modules/cli/guides/cli-reference.md` now describes both commands, exit codes, and offline usage—sync help text once implementation lands. > 2025-10-27: CLI reference now reflects final summary fields/JSON schema, quickstart includes verification/dry-run workflows, and API reference tables list both `sources ingest --dry-run` and `aoc verify`. ## Policy Engine v2 diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/TASKS.md index de8a2afe..b5a1a05d 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cccs/TASKS.md @@ -1,12 +1,12 @@ -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|FEEDCONN-CCCS-02-001 Catalogue official CCCS advisory feeds|BE-Conn-CCCS|Research|**DONE (2025-10-11)** – Resolved RSS→Atom redirects (`/api/cccs/rss/v1/get?...` → `/api/cccs/atom/v1/get?...`), confirmed feed caps at 50 entries with inline HTML bodies, no `Last-Modified`/`ETag`, and `updated` timestamps in UTC. Findings and packet captures parked in `docs/concelier-connector-research-20251011.md`; retention sweep follow-up tracked in 02-007.| -|FEEDCONN-CCCS-02-002 Implement fetch & source state handling|BE-Conn-CCCS|Source.Common, Storage.Mongo|**DONE (2025-10-14)** – `CccsConnector.FetchAsync` now hydrates feeds via `CccsFeedClient`, persists per-entry JSON payloads with SHA256 dedupe and cursor state, throttles requests, and records taxonomy + language metadata in document state.| -|FEEDCONN-CCCS-02-003 DTO/parser implementation|BE-Conn-CCCS|Source.Common|**DONE (2025-10-14)** – Added `CccsHtmlParser` to sanitize Atom body HTML, extract serial/date/product bullets, collapse whitespace, and emit normalized reference URLs; `ParseAsync` now persists DTO records under schema `cccs.dto.v1`.| -|FEEDCONN-CCCS-02-004 Canonical mapping & range primitives|BE-Conn-CCCS|Models|**DONE (2025-10-14)** – `CccsMapper` now materializes canonical advisories (aliases from serial/source/CVEs, references incl. canonical URL, vendor package records) with provenance masks; `MapAsync` stores results in `AdvisoryStore`.| -|FEEDCONN-CCCS-02-005 Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-14)** – Added English/French fixtures plus parser + connector end-to-end tests (`StellaOps.Concelier.Connector.Cccs.Tests`). Canned HTTP handler + Mongo fixture enables fetch→parse→map regression; fixtures refresh via `UPDATE_CCCS_FIXTURES=1`.| -|FEEDCONN-CCCS-02-006 Observability & documentation|DevEx|Docs|**DONE (2025-10-15)** – Added `CccsDiagnostics` meter (fetch/parse/map counters), enriched connector logs with document counts, and published `docs/ops/concelier-cccs-operations.md` covering config, telemetry, and sanitiser guidance.| -|FEEDCONN-CCCS-02-007 Historical advisory harvesting plan|BE-Conn-CCCS|Research|**DONE (2025-10-15)** – Measured `/api/cccs/threats/v1/get` inventory (~5.1k rows/lang; earliest 2018-06-08), documented backfill workflow + language split strategy, and linked the runbook for Offline Kit execution.| -|FEEDCONN-CCCS-02-008 Raw DOM parsing refinement|BE-Conn-CCCS|Source.Common|**DONE (2025-10-15)** – Parser now walks unsanitised DOM (heading + nested list coverage), sanitizer keeps ``/`section` nodes, and regression fixtures/tests assert EN/FR list handling + preserved HTML structure.| -|FEEDCONN-CCCS-02-009 Normalized versions rollout (Oct 2025)|BE-Conn-CCCS|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-21)** – Implement trailing-version split helper per Merge guidance (see `../Merge/RANGE_PRIMITIVES_COORDINATION.md` “Helper snippets”) to emit `NormalizedVersions` via `SemVerRangeRuleBuilder`; refresh mapper tests/fixtures to assert provenance notes (`cccs:{serial}:{index}`) and confirm merge counters drop.| +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|FEEDCONN-CCCS-02-001 Catalogue official CCCS advisory feeds|BE-Conn-CCCS|Research|**DONE (2025-10-11)** – Resolved RSS→Atom redirects (`/api/cccs/rss/v1/get?...` → `/api/cccs/atom/v1/get?...`), confirmed feed caps at 50 entries with inline HTML bodies, no `Last-Modified`/`ETag`, and `updated` timestamps in UTC. Findings and packet captures parked in `docs/concelier-connector-research-20251011.md`; retention sweep follow-up tracked in 02-007.| +|FEEDCONN-CCCS-02-002 Implement fetch & source state handling|BE-Conn-CCCS|Source.Common, Storage.Mongo|**DONE (2025-10-14)** – `CccsConnector.FetchAsync` now hydrates feeds via `CccsFeedClient`, persists per-entry JSON payloads with SHA256 dedupe and cursor state, throttles requests, and records taxonomy + language metadata in document state.| +|FEEDCONN-CCCS-02-003 DTO/parser implementation|BE-Conn-CCCS|Source.Common|**DONE (2025-10-14)** – Added `CccsHtmlParser` to sanitize Atom body HTML, extract serial/date/product bullets, collapse whitespace, and emit normalized reference URLs; `ParseAsync` now persists DTO records under schema `cccs.dto.v1`.| +|FEEDCONN-CCCS-02-004 Canonical mapping & range primitives|BE-Conn-CCCS|Models|**DONE (2025-10-14)** – `CccsMapper` now materializes canonical advisories (aliases from serial/source/CVEs, references incl. canonical URL, vendor package records) with provenance masks; `MapAsync` stores results in `AdvisoryStore`.| +|FEEDCONN-CCCS-02-005 Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-14)** – Added English/French fixtures plus parser + connector end-to-end tests (`StellaOps.Concelier.Connector.Cccs.Tests`). Canned HTTP handler + Mongo fixture enables fetch→parse→map regression; fixtures refresh via `UPDATE_CCCS_FIXTURES=1`.| +|FEEDCONN-CCCS-02-006 Observability & documentation|DevEx|Docs|**DONE (2025-10-15)** – Added `CccsDiagnostics` meter (fetch/parse/map counters), enriched connector logs with document counts, and published `docs/modules/concelier/operations/connectors/cccs.md` covering config, telemetry, and sanitiser guidance.| +|FEEDCONN-CCCS-02-007 Historical advisory harvesting plan|BE-Conn-CCCS|Research|**DONE (2025-10-15)** – Measured `/api/cccs/threats/v1/get` inventory (~5.1k rows/lang; earliest 2018-06-08), documented backfill workflow + language split strategy, and linked the runbook for Offline Kit execution.| +|FEEDCONN-CCCS-02-008 Raw DOM parsing refinement|BE-Conn-CCCS|Source.Common|**DONE (2025-10-15)** – Parser now walks unsanitised DOM (heading + nested list coverage), sanitizer keeps ``/`section` nodes, and regression fixtures/tests assert EN/FR list handling + preserved HTML structure.| +|FEEDCONN-CCCS-02-009 Normalized versions rollout (Oct 2025)|BE-Conn-CCCS|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-21)** – Implement trailing-version split helper per Merge guidance (see `../Merge/RANGE_PRIMITIVES_COORDINATION.md` “Helper snippets”) to emit `NormalizedVersions` via `SemVerRangeRuleBuilder`; refresh mapper tests/fixtures to assert provenance notes (`cccs:{serial}:{index}`) and confirm merge counters drop.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertBund/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertBund/TASKS.md index 3228d705..4cb60363 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertBund/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertBund/TASKS.md @@ -1,13 +1,13 @@ -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|FEEDCONN-CERTBUND-02-001 Research CERT-Bund advisory endpoints|BE-Conn-CERTBUND|Research|**DONE (2025-10-11)** – Confirmed public RSS at `https://wid.cert-bund.de/content/public/securityAdvisory/rss` (HTTP 200 w/out cookies), 250-item window, German titles/categories, and detail links pointing to Angular SPA. Captured header profile (no cache hints) and logged open item to discover the JSON API used by `portal` frontend.| -|FEEDCONN-CERTBUND-02-002 Fetch job & state persistence|BE-Conn-CERTBUND|Source.Common, Storage.Mongo|**DONE (2025-10-14)** – `CertBundConnector.FetchAsync` consumes RSS via session-bootstrapped client, stores per-advisory JSON documents with metadata + SHA, throttles detail requests, and maintains cursor state (pending docs/mappings, known advisory IDs, last published).| -|FEEDCONN-CERTBUND-02-003 Parser/DTO implementation|BE-Conn-CERTBUND|Source.Common|**DONE (2025-10-14)** – Detail JSON piped through `CertBundDetailParser` (raw DOM sanitised to HTML), capturing severity, CVEs, product list, and references into DTO records (`cert-bund.detail.v1`).| -|FEEDCONN-CERTBUND-02-004 Canonical mapping & range primitives|BE-Conn-CERTBUND|Models|**DONE (2025-10-14)** – `CertBundMapper` emits canonical advisories (aliases, references, vendor package ranges, provenance) with severity normalisation and deterministic ordering.| -|FEEDCONN-CERTBUND-02-005 Regression fixtures & tests|QA|Testing|**DONE (2025-10-14)** – Added `StellaOps.Concelier.Connector.CertBund.Tests` covering fetch→parse→map against canned RSS/JSON fixtures; integration harness uses Mongo2Go + canned HTTP handler; fixtures regenerate via `UPDATE_CERTBUND_FIXTURES=1`.| -|FEEDCONN-CERTBUND-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-15)** – Added `CertBundDiagnostics` (meter `StellaOps.Concelier.Connector.CertBund`) with fetch/parse/map counters + histograms, recorded coverage days, wired stage summary logs, and published the ops runbook (`docs/ops/concelier-certbund-operations.md`).| -|FEEDCONN-CERTBUND-02-007 Feed history & locale assessment|BE-Conn-CERTBUND|Research|**DONE (2025-10-15)** – Measured RSS retention (~6 days/≈250 items), captured connector-driven backfill guidance in the runbook, and aligned locale guidance (preserve `language=de`, Docs glossary follow-up). **Next:** coordinate with Tools to land the state-seeding helper so scripted backfills replace manual Mongo tweaks.| -|FEEDCONN-CERTBUND-02-008 Session bootstrap & cookie strategy|BE-Conn-CERTBUND|Source.Common|**DONE (2025-10-14)** – Feed client primes the portal session (cookie container via `SocketsHttpHandler`), shares cookies across detail requests, and documents bootstrap behaviour in options (`PortalBootstrapUri`).| -|FEEDCONN-CERTBUND-02-009 Offline Kit export packaging|BE-Conn-CERTBUND, Docs|Offline Kit|**DONE (2025-10-17)** – Added `tools/certbund_offline_snapshot.py` to capture search/export JSON, emit deterministic manifests + SHA files, and refreshed docs (`docs/ops/concelier-certbund-operations.md`, `docs/24_OFFLINE_KIT.md`) with offline-kit instructions and manifest layout guidance. Seed data README/ignore rules cover local snapshot hygiene.| -|FEEDCONN-CERTBUND-02-010 Normalized range translator|BE-Conn-CERTBUND|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-22)** – Translate `product.Versions` phrases (e.g., `2023.1 bis 2024.2`, `alle`) into comparator strings for `SemVerRangeRuleBuilder`, emit `NormalizedVersions` with `certbund:{advisoryId}:{vendor}` provenance, and extend tests/README with localisation notes.| +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|FEEDCONN-CERTBUND-02-001 Research CERT-Bund advisory endpoints|BE-Conn-CERTBUND|Research|**DONE (2025-10-11)** – Confirmed public RSS at `https://wid.cert-bund.de/content/public/securityAdvisory/rss` (HTTP 200 w/out cookies), 250-item window, German titles/categories, and detail links pointing to Angular SPA. Captured header profile (no cache hints) and logged open item to discover the JSON API used by `portal` frontend.| +|FEEDCONN-CERTBUND-02-002 Fetch job & state persistence|BE-Conn-CERTBUND|Source.Common, Storage.Mongo|**DONE (2025-10-14)** – `CertBundConnector.FetchAsync` consumes RSS via session-bootstrapped client, stores per-advisory JSON documents with metadata + SHA, throttles detail requests, and maintains cursor state (pending docs/mappings, known advisory IDs, last published).| +|FEEDCONN-CERTBUND-02-003 Parser/DTO implementation|BE-Conn-CERTBUND|Source.Common|**DONE (2025-10-14)** – Detail JSON piped through `CertBundDetailParser` (raw DOM sanitised to HTML), capturing severity, CVEs, product list, and references into DTO records (`cert-bund.detail.v1`).| +|FEEDCONN-CERTBUND-02-004 Canonical mapping & range primitives|BE-Conn-CERTBUND|Models|**DONE (2025-10-14)** – `CertBundMapper` emits canonical advisories (aliases, references, vendor package ranges, provenance) with severity normalisation and deterministic ordering.| +|FEEDCONN-CERTBUND-02-005 Regression fixtures & tests|QA|Testing|**DONE (2025-10-14)** – Added `StellaOps.Concelier.Connector.CertBund.Tests` covering fetch→parse→map against canned RSS/JSON fixtures; integration harness uses Mongo2Go + canned HTTP handler; fixtures regenerate via `UPDATE_CERTBUND_FIXTURES=1`.| +|FEEDCONN-CERTBUND-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-15)** – Added `CertBundDiagnostics` (meter `StellaOps.Concelier.Connector.CertBund`) with fetch/parse/map counters + histograms, recorded coverage days, wired stage summary logs, and published the ops runbook (`docs/modules/concelier/operations/connectors/certbund.md`).| +|FEEDCONN-CERTBUND-02-007 Feed history & locale assessment|BE-Conn-CERTBUND|Research|**DONE (2025-10-15)** – Measured RSS retention (~6 days/≈250 items), captured connector-driven backfill guidance in the runbook, and aligned locale guidance (preserve `language=de`, Docs glossary follow-up). **Next:** coordinate with Tools to land the state-seeding helper so scripted backfills replace manual Mongo tweaks.| +|FEEDCONN-CERTBUND-02-008 Session bootstrap & cookie strategy|BE-Conn-CERTBUND|Source.Common|**DONE (2025-10-14)** – Feed client primes the portal session (cookie container via `SocketsHttpHandler`), shares cookies across detail requests, and documents bootstrap behaviour in options (`PortalBootstrapUri`).| +|FEEDCONN-CERTBUND-02-009 Offline Kit export packaging|BE-Conn-CERTBUND, Docs|Offline Kit|**DONE (2025-10-17)** – Added `src/Tools/certbund_offline_snapshot.py` to capture search/export JSON, emit deterministic manifests + SHA files, and refreshed docs (`docs/modules/concelier/operations/connectors/certbund.md`, `docs/24_OFFLINE_KIT.md`) with offline-kit instructions and manifest layout guidance. Seed data README/ignore rules cover local snapshot hygiene.| +|FEEDCONN-CERTBUND-02-010 Normalized range translator|BE-Conn-CERTBUND|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-22)** – Translate `product.Versions` phrases (e.g., `2023.1 bis 2024.2`, `alle`) into comparator strings for `SemVerRangeRuleBuilder`, emit `NormalizedVersions` with `certbund:{advisoryId}:{vendor}` provenance, and extend tests/README with localisation notes.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md index 54d329d5..b30b5882 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.CertCc/FEEDCONN-CERTCC-02-009_PLAN.md @@ -34,7 +34,7 @@ - Dashboards: `certcc.*` meters (plan, summary fetch, detail fetch) plus `concelier.range.primitives` with tag `scheme=certcc.vendor`. - Logs: ensure Parse/Map jobs emit `correlationId` aligned with fetch events for traceability. -- Data QA: run `tools/dump_advisory` against two VINCE notes (one multi-vendor, one single-vendor) every phase to spot-check normalized versions ordering and provenance. +- Data QA: run `src/Tools/dump_advisory` against two VINCE notes (one multi-vendor, one single-vendor) every phase to spot-check normalized versions ordering and provenance. - Storage: verify Mongo TTL/size for `raw_documents` and `dtos`—detail payload volume increases by ~3× when mapping resumes. ## 5. Rollback / Contingency Playbook diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cve/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cve/TASKS.md index 5188b09d..583bd862 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cve/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Cve/TASKS.md @@ -7,6 +7,6 @@ |Canonical mapping & range primitives|BE-Conn-CVE|Models|**DONE (2025-10-10)** – `CveMapper` emits canonical advisories, vendor range primitives, SemVer/range statuses, references, CVSS normalization.
2025-10-11 research trail: confirm subsequent MR adds `NormalizedVersions` shaped like `[{"scheme":"semver","type":"range","min":"","minInclusive":true,"max":"","maxInclusive":false,"notes":"nvd:CVE-2025-XXXX"}]` so storage provenance joins continue to work.| |Deterministic tests & fixtures|QA|Testing|**DONE (2025-10-10)** – Added `StellaOps.Concelier.Connector.Cve.Tests` harness with canned fixtures + snapshot regression covering fetch/parse/map.| |Observability & docs|DevEx|Docs|**DONE (2025-10-10)** – Diagnostics meter (`cve.fetch.*`, etc.) wired; options/usage documented via `CveServiceCollectionExtensions`.| -|Operator rollout playbook|BE-Conn-CVE, Ops|Docs|**DONE (2025-10-12)** – Refreshed `docs/ops/concelier-cve-kev-operations.md` with credential checklist, smoke book, PromQL guardrails, and linked Grafana pack (`docs/ops/concelier-cve-kev-grafana-dashboard.json`).| -|Live smoke & monitoring|QA, BE-Conn-CVE|WebService, Observability|**DONE (2025-10-15)** – Executed connector harness smoke using CVE Services sample window (CVE-2024-0001), confirmed fetch/parse/map telemetry (`cve.fetch.*`, `cve.map.success`) all incremented once, and archived the summary log + Grafana import guidance in `docs/ops/concelier-cve-kev-operations.md` (“Staging smoke 2025-10-15”).| +|Operator rollout playbook|BE-Conn-CVE, Ops|Docs|**DONE (2025-10-12)** – Refreshed `docs/modules/concelier/operations/connectors/cve-kev.md` with credential checklist, smoke book, PromQL guardrails, and linked Grafana pack (`docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json`).| +|Live smoke & monitoring|QA, BE-Conn-CVE|WebService, Observability|**DONE (2025-10-15)** – Executed connector harness smoke using CVE Services sample window (CVE-2024-0001), confirmed fetch/parse/map telemetry (`cve.fetch.*`, `cve.map.success`) all incremented once, and archived the summary log + Grafana import guidance in `docs/modules/concelier/operations/connectors/cve-kev.md` (“Staging smoke 2025-10-15”).| |FEEDCONN-CVE-02-003 Normalized versions rollout|BE-Conn-CVE|Models `FEEDMODELS-SCHEMA-01-003`, Normalization playbook|**DONE (2025-10-12)** – Confirmed SemVer primitives map to normalized rules with `cve:{cveId}:{identifier}` notes and refreshed snapshots; `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Cve.Tests` passes on net10 preview.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ghsa/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ghsa/TASKS.md index 2847d98e..223b1a53 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ghsa/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ghsa/TASKS.md @@ -8,10 +8,10 @@ |Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-10)** – New `StellaOps.Concelier.Connector.Ghsa.Tests` regression covers fetch/parse/map via canned GHSA fixtures and snapshot assertions.| |Telemetry & documentation|DevEx|Docs|**DONE (2025-10-10)** – Diagnostics meter (`ghsa.fetch.*`) wired; DI extension documents token/headers and job registrations.| |GitHub quota monitoring & retries|BE-Conn-GHSA, Observability|Source.Common|**DONE (2025-10-12)** – Rate-limit metrics/logs added, retry/backoff handles 403 secondary limits, and ops runbook documents dashboards + mitigation steps.| -|Production credential & scheduler rollout|Ops, BE-Conn-GHSA|Docs, WebService|**DONE (2025-10-12)** – Scheduler defaults registered via `JobSchedulerBuilder`, credential provisioning documented (Compose/Helm samples), and staged backfill guidance captured in `docs/ops/concelier-ghsa-operations.md`.| +|Production credential & scheduler rollout|Ops, BE-Conn-GHSA|Docs, WebService|**DONE (2025-10-12)** – Scheduler defaults registered via `JobSchedulerBuilder`, credential provisioning documented (Compose/Helm samples), and staged backfill guidance captured in `docs/modules/concelier/operations/connectors/ghsa.md`.| |FEEDCONN-GHSA-04-002 Conflict regression fixtures|BE-Conn-GHSA, QA|Merge `FEEDMERGE-ENGINE-04-001`|**DONE (2025-10-12)** – Added `conflict-ghsa.canonical.json` + `GhsaConflictFixtureTests`; SemVer ranges and credits align with merge precedence triple and shareable with QA. Validation: `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Ghsa.Tests/StellaOps.Concelier.Connector.Ghsa.Tests.csproj --filter GhsaConflictFixtureTests`.| |FEEDCONN-GHSA-02-004 GHSA credits & ecosystem severity mapping|BE-Conn-GHSA|Models `FEEDMODELS-SCHEMA-01-002`|**DONE (2025-10-11)** – Mapper emits advisory credits with provenance masks, fixtures assert role/contact ordering, and severity normalization remains unchanged.| -|FEEDCONN-GHSA-02-007 Credit parity regression fixtures|BE-Conn-GHSA, QA|Source.Nvd, Source.Osv|**DONE (2025-10-12)** – Parity fixtures regenerated via `tools/FixtureUpdater`, normalized SemVer notes verified against GHSA/NVD/OSV snapshots, and the fixtures guide now documents the headroom checks.| +|FEEDCONN-GHSA-02-007 Credit parity regression fixtures|BE-Conn-GHSA, QA|Source.Nvd, Source.Osv|**DONE (2025-10-12)** – Parity fixtures regenerated via `src/Tools/FixtureUpdater`, normalized SemVer notes verified against GHSA/NVD/OSV snapshots, and the fixtures guide now documents the headroom checks.| |FEEDCONN-GHSA-02-001 Normalized versions rollout|BE-Conn-GHSA|Models `FEEDMODELS-SCHEMA-01-003`, Normalization playbook|**DONE (2025-10-11)** – GHSA mapper now emits SemVer primitives + normalized ranges, fixtures refreshed, connector tests passing; report logged via FEEDMERGE-COORD-02-900.| |FEEDCONN-GHSA-02-005 Quota monitoring hardening|BE-Conn-GHSA, Observability|Source.Common metrics|**DONE (2025-10-12)** – Diagnostics expose headroom histograms/gauges, warning logs dedupe below the configured threshold, and the ops runbook gained alerting and mitigation guidance.| |FEEDCONN-GHSA-02-006 Scheduler rollout integration|BE-Conn-GHSA, Ops|Job scheduler|**DONE (2025-10-12)** – Dependency routine tests assert cron/timeouts, and the runbook highlights cron overrides plus backoff toggles for staged rollouts.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md index 7eb4b9fe..058baea6 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ics.Cisa/TASKS.md @@ -9,7 +9,7 @@ |FEEDCONN-ICSCISA-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-16)** – Ops guide documents attachment checks, SemVer exact values, and proxy guidance; diagnostics remain unchanged.| |FEEDCONN-ICSCISA-02-007 Detail document inventory|BE-Conn-ICS-CISA|Research|**DONE (2025-10-16)** – Validated canned detail pages vs feed output so attachment inventories stay aligned; archived expectations noted in `HANDOVER.md`.| |FEEDCONN-ICSCISA-02-008 Distribution fallback strategy|BE-Conn-ICS-CISA|Research|**DONE (2025-10-11)** – Outlined GovDelivery token request, HTML scrape + email digest fallback, and dependency on Ops for credential workflow; awaiting decision before fetch implementation.| -|FEEDCONN-ICSCISA-02-009 GovDelivery credential onboarding|Ops, BE-Conn-ICS-CISA|Ops|**DONE (2025-10-14)** – GovDelivery onboarding runbook captured in `docs/ops/concelier-icscisa-operations.md`; secret vault path and Offline Kit handling documented.| +|FEEDCONN-ICSCISA-02-009 GovDelivery credential onboarding|Ops, BE-Conn-ICS-CISA|Ops|**DONE (2025-10-14)** – GovDelivery onboarding runbook captured in `docs/modules/concelier/operations/connectors/ics-cisa.md`; secret vault path and Offline Kit handling documented.| |FEEDCONN-ICSCISA-02-010 Mitigation & SemVer polish|BE-Conn-ICS-CISA|02-003, 02-004|**DONE (2025-10-16)** – Attachment + mitigation references now land as expected and SemVer primitives carry exact values; end-to-end suite green (see `HANDOVER.md`).| |FEEDCONN-ICSCISA-02-011 Docs & telemetry refresh|DevEx|02-006|**DONE (2025-10-16)** – Ops documentation refreshed (attachments, SemVer validation, proxy knobs) and telemetry notes verified.| |FEEDCONN-ICSCISA-02-012 Normalized version decision|BE-Conn-ICS-CISA|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-23)** – Promote existing `SemVerPrimitive` exact values into `NormalizedVersions` via `.ToNormalizedVersionRule("ics-cisa:{advisoryId}:{product}")`, add regression coverage, and open Models ticket if non-SemVer firmware requires a new scheme.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/TASKS.md index 91eb7ad5..22a55558 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Kev/TASKS.md @@ -8,5 +8,5 @@ |Deterministic fixtures/tests|QA|Testing|**DONE** – End-to-end fetch→parse→map test with canned catalog + snapshot (`UPDATE_KEV_FIXTURES=1`) guards determinism.| |Telemetry & docs|DevEx|Docs|**DONE** – Connector emits structured logs + meters for catalog entries/advisories and AGENTS docs cover cadence/allowlist guidance.| |Schema validation & anomaly surfacing|BE-Conn-KEV, QA|Source.Common|**DONE (2025-10-12)** – Wired `IJsonSchemaValidator` + embedded schema, added failure reasons (`schema`, `download`, `invalidJson`, etc.), anomaly counters (`missingCveId`, `countMismatch`, `nullEntry`), and kept `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Kev.Tests` passing.| -|Metrics export wiring|DevOps, DevEx|Observability|**DONE (2025-10-12)** – Added `kev.fetch.*` counters, parse failure/anomaly tags, refreshed ops runbook + Grafana dashboard (`docs/ops/concelier-cve-kev-grafana-dashboard.json`) with PromQL guidance.| +|Metrics export wiring|DevOps, DevEx|Observability|**DONE (2025-10-12)** – Added `kev.fetch.*` counters, parse failure/anomaly tags, refreshed ops runbook + Grafana dashboard (`docs/modules/concelier/operations/connectors/cve-kev-grafana-dashboard.json`) with PromQL guidance.| |FEEDCONN-KEV-02-003 Normalized versions propagation|BE-Conn-KEV|Models `FEEDMODELS-SCHEMA-01-003`, Normalization playbook|**DONE (2025-10-12)** – Validated catalog/date/due normalized rules emission + ordering; fixtures assert rule set and `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Kev.Tests` remains green.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/TASKS.md index cdf91137..513e3688 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Osv/TASKS.md @@ -17,4 +17,4 @@ |FEEDCONN-OSV-04-003 Parity fixture refresh|QA, BE-Conn-OSV|Normalized versions rollout, GHSA parity tests|**DONE (2025-10-12)** – Parity fixtures include normalizedVersions notes (`osv:::`); regression math rerun via `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests` and docs flagged for workflow sync.| |FEEDCONN-OSV-04-002 Conflict regression fixtures|BE-Conn-OSV, QA|Merge `FEEDMERGE-ENGINE-04-001`|**DONE (2025-10-12)** – Added `conflict-osv.canonical.json` + regression asserting SemVer range + CVSS medium severity; dataset matches GHSA/NVD fixtures for merge tests. Validation: `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csproj --filter OsvConflictFixtureTests`.| |FEEDCONN-OSV-04-004 Description/CWE/metric parity rollout|BE-Conn-OSV|Models, Core|**DONE (2025-10-15)** – OSV mapper writes advisory descriptions, `database_specific.cwe_ids` weaknesses, and canonical CVSS metric id. Parity fixtures (`osv-ghsa.*`, `osv-npm.snapshot.json`, `osv-pypi.snapshot.json`) refreshed and status communicated to Merge coordination.| -|FEEDCONN-OSV-04-005 Canonical metric fallbacks & CWE notes|BE-Conn-OSV|Models, Merge|**DONE (2025-10-16)** – Add fallback logic and metrics for advisories lacking CVSS vectors, enrich CWE provenance notes, and document merge/export expectations; refresh parity fixtures accordingly.
2025-10-16: Mapper now emits `osv:severity/` canonical ids for severity-only advisories, weakness provenance carries `database_specific.cwe_ids`, diagnostics expose `osv.map.canonical_metric_fallbacks`, parity fixtures regenerated, and ops notes added in `docs/ops/concelier-osv-operations.md`. Tests: `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csproj`.| +|FEEDCONN-OSV-04-005 Canonical metric fallbacks & CWE notes|BE-Conn-OSV|Models, Merge|**DONE (2025-10-16)** – Add fallback logic and metrics for advisories lacking CVSS vectors, enrich CWE provenance notes, and document merge/export expectations; refresh parity fixtures accordingly.
2025-10-16: Mapper now emits `osv:severity/` canonical ids for severity-only advisories, weakness provenance carries `database_specific.cwe_ids`, diagnostics expose `osv.map.canonical_metric_fallbacks`, parity fixtures regenerated, and ops notes added in `docs/modules/concelier/operations/connectors/osv.md`. Tests: `dotnet test src/Concelier/StellaOps.Concelier.PluginBinaries/StellaOps.Concelier.Connector.Osv.Tests/StellaOps.Concelier.Connector.Osv.Tests.csproj`.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/TASKS.md index d41ef558..16b1bb90 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Ru.Nkcki/TASKS.md @@ -1,11 +1,11 @@ -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|FEEDCONN-NKCKI-02-001 Research NKTsKI advisory feeds|BE-Conn-Nkcki|Research|**DONE (2025-10-11)** – Candidate RSS locations (`https://cert.gov.ru/rss/advisories.xml`, `https://www.cert.gov.ru/...`) return 403/404 even with `Accept-Language: ru-RU` and `--insecure`; site is Bitrix-backed and expects Russian Trusted Sub CA plus session cookies. Logged packet captures + needed cert list in `docs/concelier-connector-research-20251011.md`; waiting on Ops for sanctioned trust bundle.| -|FEEDCONN-NKCKI-02-002 Fetch pipeline & state persistence|BE-Conn-Nkcki|Source.Common, Storage.Mongo|**DONE (2025-10-13)** – Listing fetch now honours `maxListingPagesPerFetch`, persists cache hits when listing access fails, and records telemetry via `RuNkckiDiagnostics`. Cursor tracking covers pending documents/mappings and the known bulletin ring buffer.| -|FEEDCONN-NKCKI-02-003 DTO & parser implementation|BE-Conn-Nkcki|Source.Common|**DONE (2025-10-13)** – Parser normalises nested arrays (ICS categories, vulnerable software lists, optional tags), flattens multiline `software_text`, and guarantees deterministic ordering for URLs and tags.| -|FEEDCONN-NKCKI-02-004 Canonical mapping & range primitives|BE-Conn-Nkcki|Models|**DONE (2025-10-13)** – Mapper splits structured software entries, emits SemVer range primitives + normalized rules, deduplicates references, and surfaces CVSS v4 metadata alongside existing metrics.| -|FEEDCONN-NKCKI-02-005 Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-13)** – Fixtures refreshed with multi-page pagination + multi-entry bulletins. Tests exercise cache replay and rely on bundled OpenSSL 1.1 libs in `tools/openssl/linux-x64` to keep Mongo2Go green on modern distros.| -|FEEDCONN-NKCKI-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-13)** – Added connector-specific metrics (`nkcki.*`) and documented configuration/operational guidance in `docs/ops/concelier-nkcki-operations.md`.| -|FEEDCONN-NKCKI-02-007 Archive ingestion strategy|BE-Conn-Nkcki|Research|**DONE (2025-10-13)** – Documented Bitrix pagination/backfill plan (cache-first, offline replay, HTML/PDF capture) in `docs/ops/concelier-nkcki-operations.md`.| -|FEEDCONN-NKCKI-02-008 Access enablement plan|BE-Conn-Nkcki|Source.Common|**DONE (2025-10-11)** – Documented trust-store requirement, optional SOCKS proxy fallback, and monitoring plan; shared TLS support now available via `SourceHttpClientOptions.TrustedRootCertificates` (`concelier:httpClients:source.nkcki:*`), awaiting Ops-sourced cert bundle before fetch implementation.| +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|FEEDCONN-NKCKI-02-001 Research NKTsKI advisory feeds|BE-Conn-Nkcki|Research|**DONE (2025-10-11)** – Candidate RSS locations (`https://cert.gov.ru/rss/advisories.xml`, `https://www.cert.gov.ru/...`) return 403/404 even with `Accept-Language: ru-RU` and `--insecure`; site is Bitrix-backed and expects Russian Trusted Sub CA plus session cookies. Logged packet captures + needed cert list in `docs/concelier-connector-research-20251011.md`; waiting on Ops for sanctioned trust bundle.| +|FEEDCONN-NKCKI-02-002 Fetch pipeline & state persistence|BE-Conn-Nkcki|Source.Common, Storage.Mongo|**DONE (2025-10-13)** – Listing fetch now honours `maxListingPagesPerFetch`, persists cache hits when listing access fails, and records telemetry via `RuNkckiDiagnostics`. Cursor tracking covers pending documents/mappings and the known bulletin ring buffer.| +|FEEDCONN-NKCKI-02-003 DTO & parser implementation|BE-Conn-Nkcki|Source.Common|**DONE (2025-10-13)** – Parser normalises nested arrays (ICS categories, vulnerable software lists, optional tags), flattens multiline `software_text`, and guarantees deterministic ordering for URLs and tags.| +|FEEDCONN-NKCKI-02-004 Canonical mapping & range primitives|BE-Conn-Nkcki|Models|**DONE (2025-10-13)** – Mapper splits structured software entries, emits SemVer range primitives + normalized rules, deduplicates references, and surfaces CVSS v4 metadata alongside existing metrics.| +|FEEDCONN-NKCKI-02-005 Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-13)** – Fixtures refreshed with multi-page pagination + multi-entry bulletins. Tests exercise cache replay and rely on bundled OpenSSL 1.1 libs in `src/Tools/openssl/linux-x64` to keep Mongo2Go green on modern distros.| +|FEEDCONN-NKCKI-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-13)** – Added connector-specific metrics (`nkcki.*`) and documented configuration/operational guidance in `docs/modules/concelier/operations/connectors/nkcki.md`.| +|FEEDCONN-NKCKI-02-007 Archive ingestion strategy|BE-Conn-Nkcki|Research|**DONE (2025-10-13)** – Documented Bitrix pagination/backfill plan (cache-first, offline replay, HTML/PDF capture) in `docs/modules/concelier/operations/connectors/nkcki.md`.| +|FEEDCONN-NKCKI-02-008 Access enablement plan|BE-Conn-Nkcki|Source.Common|**DONE (2025-10-11)** – Documented trust-store requirement, optional SOCKS proxy fallback, and monitoring plan; shared TLS support now available via `SourceHttpClientOptions.TrustedRootCertificates` (`concelier:httpClients:source.nkcki:*`), awaiting Ops-sourced cert bundle before fetch implementation.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md index 90245bc7..ff9fe4aa 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Apple/TASKS.md @@ -1,11 +1,11 @@ -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|Catalogue Apple security bulletin sources|BE-Conn-Apple|Research|**DONE** – Feed contract documented in README (Software Lookup Service JSON + HT article hub) with rate-limit notes.| -|Fetch pipeline & state persistence|BE-Conn-Apple|Source.Common, Storage.Mongo|**DONE** – Index fetch + detail ingestion with SourceState cursoring/allowlists committed; awaiting live smoke run before enabling in scheduler defaults.| -|Parser & DTO implementation|BE-Conn-Apple|Source.Common|**DONE** – AngleSharp detail parser produces canonical DTO payloads (CVE list, timestamps, affected tables) persisted via DTO store.| -|Canonical mapping & range primitives|BE-Conn-Apple|Models|**DONE** – Mapper now emits SemVer-derived normalizedVersions with `apple::` notes; fixtures updated to assert canonical rules while we continue tracking multi-device coverage in follow-up tasks.
2025-10-11 research trail: confirmed payload aligns with `[{"scheme":"semver","type":"range","min":"","minInclusive":true,"max":"","maxInclusive":false,"notes":"apple:ios:17.1"}]`; continue using `notes` to surface build identifiers for storage provenance.| -|Deterministic fixtures/tests|QA|Testing|**DONE (2025-10-12)** – Parser now scopes references to article content, sorts affected rows deterministically, and regenerated fixtures (125326/125328/106355/HT214108/HT215500) produce stable JSON + sanitizer HTML in English.| -|Telemetry & documentation|DevEx|Docs|**DONE (2025-10-12)** – OpenTelemetry pipeline exports `StellaOps.Concelier.Connector.Vndr.Apple`; runbook `docs/ops/concelier-apple-operations.md` added with metrics + monitoring guidance.| -|Live HTML regression sweep|QA|Source.Common|**DONE (2025-10-12)** – Captured latest support.apple.com articles for 125326/125328/106355/HT214108/HT215500, trimmed nav noise, and committed sanitized HTML + expected DTOs with invariant timestamps.| -|Fixture regeneration tooling|DevEx|Testing|**DONE (2025-10-12)** – `scripts/update-apple-fixtures.(sh|ps1)` set the env flag + sentinel, forward through WSLENV, and clean up after regeneration; README references updated usage.| +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|Catalogue Apple security bulletin sources|BE-Conn-Apple|Research|**DONE** – Feed contract documented in README (Software Lookup Service JSON + HT article hub) with rate-limit notes.| +|Fetch pipeline & state persistence|BE-Conn-Apple|Source.Common, Storage.Mongo|**DONE** – Index fetch + detail ingestion with SourceState cursoring/allowlists committed; awaiting live smoke run before enabling in scheduler defaults.| +|Parser & DTO implementation|BE-Conn-Apple|Source.Common|**DONE** – AngleSharp detail parser produces canonical DTO payloads (CVE list, timestamps, affected tables) persisted via DTO store.| +|Canonical mapping & range primitives|BE-Conn-Apple|Models|**DONE** – Mapper now emits SemVer-derived normalizedVersions with `apple::` notes; fixtures updated to assert canonical rules while we continue tracking multi-device coverage in follow-up tasks.
2025-10-11 research trail: confirmed payload aligns with `[{"scheme":"semver","type":"range","min":"","minInclusive":true,"max":"","maxInclusive":false,"notes":"apple:ios:17.1"}]`; continue using `notes` to surface build identifiers for storage provenance.| +|Deterministic fixtures/tests|QA|Testing|**DONE (2025-10-12)** – Parser now scopes references to article content, sorts affected rows deterministically, and regenerated fixtures (125326/125328/106355/HT214108/HT215500) produce stable JSON + sanitizer HTML in English.| +|Telemetry & documentation|DevEx|Docs|**DONE (2025-10-12)** – OpenTelemetry pipeline exports `StellaOps.Concelier.Connector.Vndr.Apple`; runbook `docs/modules/concelier/operations/connectors/apple.md` added with metrics + monitoring guidance.| +|Live HTML regression sweep|QA|Source.Common|**DONE (2025-10-12)** – Captured latest support.apple.com articles for 125326/125328/106355/HT214108/HT215500, trimmed nav noise, and committed sanitized HTML + expected DTOs with invariant timestamps.| +|Fixture regeneration tooling|DevEx|Testing|**DONE (2025-10-12)** – `scripts/update-apple-fixtures.(sh|ps1)` set the env flag + sentinel, forward through WSLENV, and clean up after regeneration; README references updated usage.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/TASKS.md index 475e95fd..710e67a3 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Cisco/TASKS.md @@ -1,12 +1,12 @@ -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|FEEDCONN-CISCO-02-001 Confirm Cisco PSIRT data source|BE-Conn-Cisco|Research|**DONE (2025-10-11)** – Selected openVuln REST API (`https://apix.cisco.com/security/advisories/v2/…`) as primary (structured JSON, CSAF/CVRF links) with RSS as fallback. Documented OAuth2 client-credentials flow (`cloudsso.cisco.com/as/token.oauth2`), baseline quotas (5 req/s, 30 req/min, 5 000 req/day), and pagination contract (`pageIndex`, `pageSize≤100`) in `docs/concelier-connector-research-20251011.md`.| -|FEEDCONN-CISCO-02-002 Fetch pipeline & state persistence|BE-Conn-Cisco|Source.Common, Storage.Mongo|**DONE (2025-10-14)** – Fetch job now streams openVuln pages with OAuth bearer handler, honours 429 `Retry-After`, persists per-advisory JSON + metadata into GridFS, and updates cursor (`lastModified`, advisory ID, pending docs).| -|FEEDCONN-CISCO-02-003 Parser & DTO implementation|BE-Conn-Cisco|Source.Common|**DONE (2025-10-14)** – DTO factory normalizes SIR, folds CSAF product statuses, and persists `cisco.dto.v1` payloads (see `CiscoDtoFactory`).| -|FEEDCONN-CISCO-02-004 Canonical mapping & range primitives|BE-Conn-Cisco|Models|**DONE (2025-10-14)** – `CiscoMapper` emits canonical advisories with vendor + SemVer primitives, provenance, and status tags.| -|FEEDCONN-CISCO-02-005 Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-14)** – Added unit tests (`StellaOps.Concelier.Connector.Vndr.Cisco.Tests`) exercising DTO/mapper pipelines; `dotnet test` validated.| -|FEEDCONN-CISCO-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-14)** – Cisco diagnostics counters exposed and ops runbook updated with telemetry guidance (`docs/ops/concelier-cisco-operations.md`).| -|FEEDCONN-CISCO-02-007 API selection decision memo|BE-Conn-Cisco|Research|**DONE (2025-10-11)** – Drafted decision matrix: openVuln (structured/delta filters, OAuth throttle) vs RSS (delayed/minimal metadata). Pending OAuth onboarding (`FEEDCONN-CISCO-02-008`) before final recommendation circulated.| -|FEEDCONN-CISCO-02-008 OAuth client provisioning|Ops, BE-Conn-Cisco|Ops|**DONE (2025-10-14)** – `docs/ops/concelier-cisco-operations.md` documents OAuth provisioning/rotation, quotas, and Offline Kit distribution guidance.| -|FEEDCONN-CISCO-02-009 Normalized SemVer promotion|BE-Conn-Cisco|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-21)** – Use helper from `../Merge/RANGE_PRIMITIVES_COORDINATION.md` to convert `SemVerPrimitive` outputs into `NormalizedVersionRule` with provenance (`cisco:{productId}`), update mapper/tests, and confirm merge normalized-rule counters drop.| +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|FEEDCONN-CISCO-02-001 Confirm Cisco PSIRT data source|BE-Conn-Cisco|Research|**DONE (2025-10-11)** – Selected openVuln REST API (`https://apix.cisco.com/security/advisories/v2/…`) as primary (structured JSON, CSAF/CVRF links) with RSS as fallback. Documented OAuth2 client-credentials flow (`cloudsso.cisco.com/as/token.oauth2`), baseline quotas (5 req/s, 30 req/min, 5 000 req/day), and pagination contract (`pageIndex`, `pageSize≤100`) in `docs/concelier-connector-research-20251011.md`.| +|FEEDCONN-CISCO-02-002 Fetch pipeline & state persistence|BE-Conn-Cisco|Source.Common, Storage.Mongo|**DONE (2025-10-14)** – Fetch job now streams openVuln pages with OAuth bearer handler, honours 429 `Retry-After`, persists per-advisory JSON + metadata into GridFS, and updates cursor (`lastModified`, advisory ID, pending docs).| +|FEEDCONN-CISCO-02-003 Parser & DTO implementation|BE-Conn-Cisco|Source.Common|**DONE (2025-10-14)** – DTO factory normalizes SIR, folds CSAF product statuses, and persists `cisco.dto.v1` payloads (see `CiscoDtoFactory`).| +|FEEDCONN-CISCO-02-004 Canonical mapping & range primitives|BE-Conn-Cisco|Models|**DONE (2025-10-14)** – `CiscoMapper` emits canonical advisories with vendor + SemVer primitives, provenance, and status tags.| +|FEEDCONN-CISCO-02-005 Deterministic fixtures & tests|QA|Testing|**DONE (2025-10-14)** – Added unit tests (`StellaOps.Concelier.Connector.Vndr.Cisco.Tests`) exercising DTO/mapper pipelines; `dotnet test` validated.| +|FEEDCONN-CISCO-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-14)** – Cisco diagnostics counters exposed and ops runbook updated with telemetry guidance (`docs/modules/concelier/operations/connectors/cisco.md`).| +|FEEDCONN-CISCO-02-007 API selection decision memo|BE-Conn-Cisco|Research|**DONE (2025-10-11)** – Drafted decision matrix: openVuln (structured/delta filters, OAuth throttle) vs RSS (delayed/minimal metadata). Pending OAuth onboarding (`FEEDCONN-CISCO-02-008`) before final recommendation circulated.| +|FEEDCONN-CISCO-02-008 OAuth client provisioning|Ops, BE-Conn-Cisco|Ops|**DONE (2025-10-14)** – `docs/modules/concelier/operations/connectors/cisco.md` documents OAuth provisioning/rotation, quotas, and Offline Kit distribution guidance.| +|FEEDCONN-CISCO-02-009 Normalized SemVer promotion|BE-Conn-Cisco|Merge coordination (`FEEDMERGE-COORD-02-900`)|**TODO (due 2025-10-21)** – Use helper from `../Merge/RANGE_PRIMITIVES_COORDINATION.md` to convert `SemVerPrimitive` outputs into `NormalizedVersionRule` with provenance (`cisco:{productId}`), update mapper/tests, and confirm merge normalized-rule counters drop.| diff --git a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/TASKS.md b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/TASKS.md index 067596e1..6b8e9c8c 100644 --- a/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/TASKS.md +++ b/src/Concelier/__Libraries/StellaOps.Concelier.Connector.Vndr.Msrc/TASKS.md @@ -1,11 +1,11 @@ -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|FEEDCONN-MSRC-02-001 Document MSRC Security Update Guide API|BE-Conn-MSRC|Research|**DONE (2025-10-11)** – Confirmed REST endpoint (`https://api.msrc.microsoft.com/sug/v2.0/en-US/vulnerabilities`) + CVRF ZIP download flow, required Azure AD client-credentials scope (`api://api.msrc.microsoft.com/.default`), mandatory `api-version=2024-08-01` header, and delta params (`lastModifiedStartDateTime`, `lastModifiedEndDateTime`). Findings recorded in `docs/concelier-connector-research-20251011.md`.| -|FEEDCONN-MSRC-02-002 Fetch pipeline & source state|BE-Conn-MSRC|Source.Common, Storage.Mongo|**DONE (2025-10-15)** – Added `MsrcApiClient` + token provider, cursor overlap handling, and detail persistence via GridFS (metadata carries CVRF URL + timestamps). State tracks `lastModifiedCursor` with configurable overlap/backoff. **Next:** coordinate with Tools on shared state-seeding helper once CVRF download flag stabilises.| -|FEEDCONN-MSRC-02-003 Parser & DTO implementation|BE-Conn-MSRC|Source.Common|**DONE (2025-10-15)** – Implemented `MsrcDetailParser`/DTOs capturing threats, remediations, KB IDs, CVEs, CVSS, and affected products (build/platform metadata preserved).| -|FEEDCONN-MSRC-02-004 Canonical mapping & range primitives|BE-Conn-MSRC|Models|**DONE (2025-10-15)** – `MsrcMapper` emits aliases (MSRC ID/CVE/KB), references (release notes + CVRF), vendor packages with `msrc.build` normalized rules, and CVSS provenance.| -|FEEDCONN-MSRC-02-005 Deterministic fixtures/tests|QA|Testing|**DONE (2025-10-15)** – Added `StellaOps.Concelier.Connector.Vndr.Msrc.Tests` with canned token/summary/detail responses and snapshot assertions via Mongo2Go. Fixtures regenerate via `UPDATE_MSRC_FIXTURES`.| -|FEEDCONN-MSRC-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-15)** – Introduced `MsrcDiagnostics` meter (summary/detail/parse/map metrics), structured fetch logs, README updates, and Ops brief `docs/ops/concelier-msrc-operations.md` covering AAD onboarding + CVRF handling.| -|FEEDCONN-MSRC-02-007 API contract comparison memo|BE-Conn-MSRC|Research|**DONE (2025-10-11)** – Completed memo outline recommending dual-path (REST for incremental, CVRF for offline); implementation hinges on `FEEDCONN-MSRC-02-008` AAD onboarding for token acquisition.| -|FEEDCONN-MSRC-02-008 Azure AD application onboarding|Ops, BE-Conn-MSRC|Ops|**DONE (2025-10-15)** – Coordinated Ops handoff; drafted AAD onboarding brief (`docs/ops/concelier-msrc-operations.md`) with app registration requirements, secret rotation policy, sample configuration, and CVRF mirroring guidance for Offline Kit.| +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|FEEDCONN-MSRC-02-001 Document MSRC Security Update Guide API|BE-Conn-MSRC|Research|**DONE (2025-10-11)** – Confirmed REST endpoint (`https://api.msrc.microsoft.com/sug/v2.0/en-US/vulnerabilities`) + CVRF ZIP download flow, required Azure AD client-credentials scope (`api://api.msrc.microsoft.com/.default`), mandatory `api-version=2024-08-01` header, and delta params (`lastModifiedStartDateTime`, `lastModifiedEndDateTime`). Findings recorded in `docs/concelier-connector-research-20251011.md`.| +|FEEDCONN-MSRC-02-002 Fetch pipeline & source state|BE-Conn-MSRC|Source.Common, Storage.Mongo|**DONE (2025-10-15)** – Added `MsrcApiClient` + token provider, cursor overlap handling, and detail persistence via GridFS (metadata carries CVRF URL + timestamps). State tracks `lastModifiedCursor` with configurable overlap/backoff. **Next:** coordinate with Tools on shared state-seeding helper once CVRF download flag stabilises.| +|FEEDCONN-MSRC-02-003 Parser & DTO implementation|BE-Conn-MSRC|Source.Common|**DONE (2025-10-15)** – Implemented `MsrcDetailParser`/DTOs capturing threats, remediations, KB IDs, CVEs, CVSS, and affected products (build/platform metadata preserved).| +|FEEDCONN-MSRC-02-004 Canonical mapping & range primitives|BE-Conn-MSRC|Models|**DONE (2025-10-15)** – `MsrcMapper` emits aliases (MSRC ID/CVE/KB), references (release notes + CVRF), vendor packages with `msrc.build` normalized rules, and CVSS provenance.| +|FEEDCONN-MSRC-02-005 Deterministic fixtures/tests|QA|Testing|**DONE (2025-10-15)** – Added `StellaOps.Concelier.Connector.Vndr.Msrc.Tests` with canned token/summary/detail responses and snapshot assertions via Mongo2Go. Fixtures regenerate via `UPDATE_MSRC_FIXTURES`.| +|FEEDCONN-MSRC-02-006 Telemetry & documentation|DevEx|Docs|**DONE (2025-10-15)** – Introduced `MsrcDiagnostics` meter (summary/detail/parse/map metrics), structured fetch logs, README updates, and Ops brief `docs/modules/concelier/operations/connectors/msrc.md` covering AAD onboarding + CVRF handling.| +|FEEDCONN-MSRC-02-007 API contract comparison memo|BE-Conn-MSRC|Research|**DONE (2025-10-11)** – Completed memo outline recommending dual-path (REST for incremental, CVRF for offline); implementation hinges on `FEEDCONN-MSRC-02-008` AAD onboarding for token acquisition.| +|FEEDCONN-MSRC-02-008 Azure AD application onboarding|Ops, BE-Conn-MSRC|Ops|**DONE (2025-10-15)** – Coordinated Ops handoff; drafted AAD onboarding brief (`docs/modules/concelier/operations/connectors/msrc.md`) with app registration requirements, secret rotation policy, sample configuration, and CVRF mirroring guidance for Offline Kit.| diff --git a/src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md b/src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md deleted file mode 100644 index 6c508e5a..00000000 --- a/src/DEDUP_CONFLICTS_RESOLUTION_ALGO.md +++ /dev/null @@ -1,143 +0,0 @@ -````markdown -# Concelier Vulnerability Conflict Resolution Rules - -This document defines the canonical, deterministic conflict resolution strategy for merging vulnerability data from **NVD**, **GHSA**, and **OSV** in Concelier. - ---- - -## 🧭 Source Precedence - -1. **Primary order:** - `GHSA > NVD > OSV` - - **Rationale:** - GHSA advisories are human-curated and fast to correct; NVD has the broadest CVE coverage; OSV excels in ecosystem-specific precision. - -2. **Freshness override (≥48 h):** - If a **lower-priority** source is **newer by at least 48 hours** for a freshness-sensitive field, its value overrides the higher-priority one. - Always store the decision in a provenance record. - -3. **Merge scope:** - Only merge data referring to the **same CVE ID** or the same GHSA/OSV advisory explicitly mapped to that CVE. - ---- - -## 🧩 Field-Level Precedence - -| Field | Priority | Freshness-Sensitive | Notes | -|-------|-----------|--------------------|-------| -| Title / Summary | GHSA → NVD → OSV | ✅ | Prefer concise structured titles | -| Description | GHSA → NVD → OSV | ✅ | | -| Severity (CVSS) | NVD → GHSA → OSV | ❌ | Keep all under `metrics[]`, mark `canonicalMetric` by order | -| Ecosystem Severity Label | GHSA → OSV | ❌ | Supplemental tag only | -| Affected Packages / Ranges | OSV → GHSA → NVD | ✅ | OSV strongest for SemVer normalization | -| CWE(s) | NVD → GHSA → OSV | ❌ | NVD taxonomy most stable | -| References / Links | Union of all | ✅ | Deduplicate by normalized URL | -| Credits / Acknowledgements | Union of all | ✅ | Sort by role, displayName | -| Published / Modified timestamps | Earliest published / Latest modified | ✅ | | -| EPSS / KEV / Exploit status | Specialized feed only | ❌ | Do not override manually | - ---- - -## ⚖️ Deterministic Tie-Breakers - -If precedence and freshness both tie: - -1. **Source order:** GHSA > NVD > OSV -2. **Lexicographic stability:** Prefer shorter normalized text; if equal, ASCIIbetical -3. **Stable hash of payload:** Lowest hash wins - -Each chosen value must store the merge rationale: - -```json -{ - "provenance": { - "source": "GHSA", - "kind": "merge", - "value": "description", - "decisionReason": "precedence" - } -} -```` - ---- - -## 🧮 Merge Algorithm (Pseudocode) - -```csharp -inputs: records = {ghsa?, nvd?, osv?} -out = new CanonicalVuln(CVE) - -foreach field in CANONICAL_SCHEMA: - candidates = collect(values, source, lastModified) - if freshnessSensitive(field) and newerBy48h(lowerPriority): - pick newest - else: - pick by precedence(field) - if tie: - applyTieBreakers() - out.field = normalize(field, value) - out.provenance[field] = decisionTrail - -out.references = dedupe(union(all.references)) -out.affected = normalizeAndUnion(OSV, GHSA, NVD) -out.metrics = rankAndSetCanonical(NVDv3 → GHSA → OSV → v2) -return out -``` - ---- - -## 🔧 Normalization Rules - -* **SemVer:** - Parse with tolerant builder; normalize `v` prefixes; map comparators (`<=`, `<`, `>=`, `>`); expand OSV events into continuous ranges. - -* **Packages:** - Canonical key = `(ecosystem, packageName, language?)`; maintain aliases (purl, npm, Maven GAV, etc.). - -* **CWE:** - Store both ID and name; validate against current CWE catalog. - -* **CVSS:** - Preserve provided vector and base score; recompute only for validation. - ---- - -## ✅ Output Guarantees - -| Property | Description | -| ---------------- | ------------------------------------------------------------------------------- | -| **Reproducible** | Same input → same canonical output | -| **Auditable** | Provenance stored per field | -| **Complete** | Unions with de-duplication | -| **Composable** | Future layers (KEV, EPSS, vendor advisories) can safely extend precedence rules | - ---- - -## 🧠 Example - -* GHSA summary updated on *2025-10-09* -* NVD last modified *2025-10-05* -* OSV updated *2025-10-10* - -→ **Summary:** OSV wins (freshness override) -→ **CVSS:** NVD v3.1 remains canonical -→ **Affected:** OSV ranges canonical; GHSA aliases merged - ---- - -## 🧰 Optional C# Helper Class - -`StellaOps.Concelier.Core/CanonicalMerger.cs` - -Implements: - -* `FieldPrecedenceMap` -* `FreshnessSensitiveFields` -* `ApplyTieBreakers()` -* `NormalizeAndUnion()` - -Deterministically builds `CanonicalVuln` with full provenance tracking. - -``` -``` diff --git a/src/Excititor/StellaOps.Excititor.WebService/TASKS.md b/src/Excititor/StellaOps.Excititor.WebService/TASKS.md index f04de8b7..9170b043 100644 --- a/src/Excititor/StellaOps.Excititor.WebService/TASKS.md +++ b/src/Excititor/StellaOps.Excititor.WebService/TASKS.md @@ -1,94 +1,94 @@ -# TASKS — Epic 1: Aggregation-Only Contract -> **AOC Reminder:** Excititor WebService publishes raw statements/linksets only; derived precedence/severity belongs to Policy overlays. -| ID | Status | Owner(s) | Depends on | Notes | -|---|---|---|---|---| -| EXCITITOR-WEB-AOC-19-001 `Raw VEX ingestion APIs` | TODO | Excititor WebService Guild | EXCITITOR-CORE-AOC-19-001, EXCITITOR-STORE-AOC-19-001 | Implement `POST /ingest/vex`, `GET /vex/raw*`, and `POST /aoc/verify` endpoints. Enforce Authority scopes, tenant injection, and guard pipeline to ensure only immutable VEX facts are persisted. | -> Docs alignment (2025-10-26): See AOC reference §4–5 and authority scopes doc for required tokens/behaviour. -| EXCITITOR-WEB-AOC-19-002 `AOC observability + metrics` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-WEB-AOC-19-001 | Export metrics (`ingestion_write_total`, `aoc_violation_total`, signature verification counters) and tracing spans matching Conseiller naming. Ensure structured logging includes tenant, source vendor, upstream id, and content hash. | -> Docs alignment (2025-10-26): Metrics/traces/log schema in `docs/observability/observability.md`. -| EXCITITOR-WEB-AOC-19-003 `Guard + schema test harness` | TODO | QA Guild | EXCITITOR-WEB-AOC-19-001 | Add unit/integration tests for schema validation, forbidden field rejection (`ERR_AOC_001/006/007`), and supersedes behavior using CycloneDX-VEX & CSAF fixtures with deterministic expectations. | -> Docs alignment (2025-10-26): Error codes + CLI verification in `docs/cli/cli-reference.md`. -| EXCITITOR-WEB-AOC-19-004 `Batch ingest validation` | TODO | Excititor WebService Guild, QA Guild | EXCITITOR-WEB-AOC-19-003, EXCITITOR-CORE-AOC-19-002 | Build large fixture ingest covering mixed VEX statuses, verifying raw storage parity, metrics, and CLI `aoc verify` compatibility. Document load test/runbook updates. | -> Docs alignment (2025-10-26): Offline/air-gap workflows captured in `docs/deploy/containers.md` §5. - -## Policy Engine v2 - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-POLICY-20-001 `Policy selection endpoints` | TODO | Excititor WebService Guild | WEB-POLICY-20-001, EXCITITOR-CORE-AOC-19-004 | Provide VEX lookup APIs supporting PURL/advisory batching, scope filtering, and tenant enforcement with deterministic ordering + pagination. | - -## StellaOps Console (Sprint 23) - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-CONSOLE-23-001 `VEX aggregation views` | TODO | Excititor WebService Guild, BE-Base Platform Guild | EXCITITOR-LNM-21-201, EXCITITOR-LNM-21-202 | Expose `/console/vex` endpoints returning grouped VEX statements per advisory/component with status chips, justification metadata, precedence trace pointers, and tenant-scoped filters for Console explorer. | -| EXCITITOR-CONSOLE-23-002 `Dashboard VEX deltas` | TODO | Excititor WebService Guild | EXCITITOR-CONSOLE-23-001, EXCITITOR-LNM-21-203 | Provide aggregated counts for VEX overrides (new, not_affected, revoked) powering Console dashboard + live status ticker; emit metrics for policy explain integration. | -| EXCITITOR-CONSOLE-23-003 `VEX search helpers` | TODO | Excititor WebService Guild | EXCITITOR-CONSOLE-23-001 | Deliver rapid lookup endpoints of VEX by advisory/component for Console global search; ensure response includes provenance and precedence context; include caching and RBAC. | - -## Graph Explorer v1 - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| - -## Link-Not-Merge v1 - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-LNM-21-201 `Observation APIs` | TODO | Excititor WebService Guild, BE-Base Platform Guild | EXCITITOR-LNM-21-001 | Add VEX observation read endpoints with filters, pagination, RBAC, and tenant scoping. | -| EXCITITOR-LNM-21-202 `Linkset APIs` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-002, EXCITITOR-LNM-21-003 | Implement linkset read/export/evidence endpoints returning correlation/conflict payloads and map errors to `ERR_AGG_*`. | -| EXCITITOR-LNM-21-203 `Event publishing` | TODO | Excititor WebService Guild, Platform Events Guild | EXCITITOR-LNM-21-005 | Publish `vex.linkset.updated` events, document schema, and ensure idempotent delivery. | - -## Graph & Vuln Explorer v1 - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-GRAPH-24-101 `VEX summary API` | TODO | Excititor WebService Guild | EXCITITOR-GRAPH-24-001 | Provide endpoints delivering VEX status summaries per component/asset for Vuln Explorer integration. | -| EXCITITOR-GRAPH-24-102 `Evidence batch API` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-201 | Add batch VEX observation retrieval optimized for Graph overlays/tooltips. | - -## VEX Lens (Sprint 30) - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-VEXLENS-30-001 `VEX evidence enrichers` | TODO | Excititor WebService Guild, VEX Lens Guild | EXCITITOR-VULN-29-001, VEXLENS-30-005 | Include issuer hints, signatures, and product trees in evidence payloads for VEX Lens; Label: VEX-Lens. | - -## Vulnerability Explorer (Sprint 29) - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-VULN-29-001 `VEX key canonicalization` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-001 | Canonicalize (lossless) VEX advisory/product keys (map to `advisory_key`, capture product scopes); expose original sources in `links[]`; AOC-compliant: no merge, no derived fields, no suppression; backfill existing records. | -| EXCITITOR-VULN-29-002 `Evidence retrieval` | TODO | Excititor WebService Guild | EXCITITOR-VULN-29-001, VULN-API-29-003 | Provide `/vuln/evidence/vex/{advisory_key}` returning raw VEX statements filtered by tenant/product scope for Explorer evidence tabs. | -| EXCITITOR-VULN-29-004 `Observability` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-VULN-29-001 | Add metrics/logs for VEX normalization, suppression scopes, withdrawn statements; emit events consumed by Vuln Explorer resolver. | - -## Advisory AI (Sprint 31) - -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-AIAI-31-001 `Justification enrichment` | TODO | Excititor WebService Guild | EXCITITOR-VULN-29-001 | Expose normalized VEX justifications, product trees, and paragraph anchors for Advisory AI conflict explanations. | -| EXCITITOR-AIAI-31-002 `VEX chunk API` | TODO | Excititor WebService Guild | EXCITITOR-AIAI-31-001, VEXLENS-30-006 | Provide `/vex/evidence/chunks` endpoint returning tenant-scoped VEX statements with signature metadata and scope scores for RAG. | -| EXCITITOR-AIAI-31-003 `Telemetry` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-AIAI-31-001 | Emit metrics/logs for VEX chunk usage, signature verification failures, and guardrail triggers. | - -## Observability & Forensics (Epic 15) -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-WEB-OBS-50-001 `Telemetry adoption` | TODO | Excititor WebService Guild | TELEMETRY-OBS-50-001, EXCITITOR-OBS-50-001 | Adopt telemetry core for VEX APIs, ensure responses include trace IDs & correlation headers, and update structured logging for read endpoints. | -| EXCITITOR-WEB-OBS-51-001 `Observability health endpoints` | TODO | Excititor WebService Guild | EXCITITOR-WEB-OBS-50-001, WEB-OBS-51-001 | Implement `/obs/excititor/health` summarizing ingest/link SLOs, signature failure counts, and conflict trends for Console dashboards. | -| EXCITITOR-WEB-OBS-52-001 `Timeline streaming` | TODO | Excititor WebService Guild | EXCITITOR-WEB-OBS-50-001, TIMELINE-OBS-52-003 | Provide SSE bridge for VEX timeline events with tenant filters, pagination, and guardrails. | -| EXCITITOR-WEB-OBS-53-001 `Evidence APIs` | TODO | Excititor WebService Guild, Evidence Locker Guild | EXCITITOR-OBS-53-001, EVID-OBS-53-003 | Expose `/evidence/vex/*` endpoints that fetch locker bundles, enforce scopes, and surface verification metadata. | -| EXCITITOR-WEB-OBS-54-001 `Attestation APIs` | TODO | Excititor WebService Guild | EXCITITOR-OBS-54-001, PROV-OBS-54-001 | Add `/attestations/vex/*` endpoints returning DSSE verification state, builder identity, and chain-of-custody links. | -| EXCITITOR-WEB-OBS-55-001 `Incident mode toggles` | TODO | Excititor WebService Guild, DevOps Guild | EXCITITOR-OBS-55-001, WEB-OBS-55-001 | Provide incident mode API for VEX pipelines with activation audit logs and retention override previews. | - -## Air-Gapped Mode (Epic 16) -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-WEB-AIRGAP-56-001 | TODO | Excititor WebService Guild | AIRGAP-IMP-58-001, EXCITITOR-AIRGAP-56-001 | Support mirror bundle registration via APIs, expose bundle provenance in VEX responses, and block external connectors in sealed mode. | -| EXCITITOR-WEB-AIRGAP-56-002 | TODO | Excititor WebService Guild, AirGap Time Guild | EXCITITOR-WEB-AIRGAP-56-001, AIRGAP-TIME-58-001 | Return VEX staleness metrics and time anchor info in API responses for Console/CLI use. | -| EXCITITOR-WEB-AIRGAP-57-001 | TODO | Excititor WebService Guild, AirGap Policy Guild | AIRGAP-POL-56-001 | Map sealed-mode violations to standardized error payload with remediation guidance. | -| EXCITITOR-WEB-AIRGAP-58-001 | TODO | Excititor WebService Guild, AirGap Importer Guild | EXCITITOR-WEB-AIRGAP-56-001, TIMELINE-OBS-53-001 | Emit timeline events for VEX bundle imports with bundle ID, scope, and actor metadata. | - -## SDKs & OpenAPI (Epic 17) -| ID | Status | Owner(s) | Depends on | Notes | -|----|--------|----------|------------|-------| -| EXCITITOR-WEB-OAS-61-001 | TODO | Excititor WebService Guild | OAS-61-001 | Implement `/.well-known/openapi` discovery endpoint with spec version metadata. | -| EXCITITOR-WEB-OAS-61-002 | TODO | Excititor WebService Guild | APIGOV-61-001 | Standardize error envelope responses and update controller/unit tests. | -| EXCITITOR-WEB-OAS-62-001 | TODO | Excititor WebService Guild | EXCITITOR-OAS-61-002 | Add curated examples for VEX observation/linkset endpoints and ensure portal displays them. | -| EXCITITOR-WEB-OAS-63-001 | TODO | Excititor WebService Guild, API Governance Guild | APIGOV-63-001 | Emit deprecation headers and update docs for retiring VEX APIs. | +# TASKS — Epic 1: Aggregation-Only Contract +> **AOC Reminder:** Excititor WebService publishes raw statements/linksets only; derived precedence/severity belongs to Policy overlays. +| ID | Status | Owner(s) | Depends on | Notes | +|---|---|---|---|---| +| EXCITITOR-WEB-AOC-19-001 `Raw VEX ingestion APIs` | TODO | Excititor WebService Guild | EXCITITOR-CORE-AOC-19-001, EXCITITOR-STORE-AOC-19-001 | Implement `POST /ingest/vex`, `GET /vex/raw*`, and `POST /aoc/verify` endpoints. Enforce Authority scopes, tenant injection, and guard pipeline to ensure only immutable VEX facts are persisted. | +> Docs alignment (2025-10-26): See AOC reference §4–5 and authority scopes doc for required tokens/behaviour. +| EXCITITOR-WEB-AOC-19-002 `AOC observability + metrics` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-WEB-AOC-19-001 | Export metrics (`ingestion_write_total`, `aoc_violation_total`, signature verification counters) and tracing spans matching Conseiller naming. Ensure structured logging includes tenant, source vendor, upstream id, and content hash. | +> Docs alignment (2025-10-26): Metrics/traces/log schema in `docs/observability/observability.md`. +| EXCITITOR-WEB-AOC-19-003 `Guard + schema test harness` | TODO | QA Guild | EXCITITOR-WEB-AOC-19-001 | Add unit/integration tests for schema validation, forbidden field rejection (`ERR_AOC_001/006/007`), and supersedes behavior using CycloneDX-VEX & CSAF fixtures with deterministic expectations. | +> Docs alignment (2025-10-26): Error codes + CLI verification in `docs/modules/cli/guides/cli-reference.md`. +| EXCITITOR-WEB-AOC-19-004 `Batch ingest validation` | TODO | Excititor WebService Guild, QA Guild | EXCITITOR-WEB-AOC-19-003, EXCITITOR-CORE-AOC-19-002 | Build large fixture ingest covering mixed VEX statuses, verifying raw storage parity, metrics, and CLI `aoc verify` compatibility. Document load test/runbook updates. | +> Docs alignment (2025-10-26): Offline/air-gap workflows captured in `docs/deploy/containers.md` §5. + +## Policy Engine v2 + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-POLICY-20-001 `Policy selection endpoints` | TODO | Excititor WebService Guild | WEB-POLICY-20-001, EXCITITOR-CORE-AOC-19-004 | Provide VEX lookup APIs supporting PURL/advisory batching, scope filtering, and tenant enforcement with deterministic ordering + pagination. | + +## StellaOps Console (Sprint 23) + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-CONSOLE-23-001 `VEX aggregation views` | TODO | Excititor WebService Guild, BE-Base Platform Guild | EXCITITOR-LNM-21-201, EXCITITOR-LNM-21-202 | Expose `/console/vex` endpoints returning grouped VEX statements per advisory/component with status chips, justification metadata, precedence trace pointers, and tenant-scoped filters for Console explorer. | +| EXCITITOR-CONSOLE-23-002 `Dashboard VEX deltas` | TODO | Excititor WebService Guild | EXCITITOR-CONSOLE-23-001, EXCITITOR-LNM-21-203 | Provide aggregated counts for VEX overrides (new, not_affected, revoked) powering Console dashboard + live status ticker; emit metrics for policy explain integration. | +| EXCITITOR-CONSOLE-23-003 `VEX search helpers` | TODO | Excititor WebService Guild | EXCITITOR-CONSOLE-23-001 | Deliver rapid lookup endpoints of VEX by advisory/component for Console global search; ensure response includes provenance and precedence context; include caching and RBAC. | + +## Graph Explorer v1 + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| + +## Link-Not-Merge v1 + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-LNM-21-201 `Observation APIs` | TODO | Excititor WebService Guild, BE-Base Platform Guild | EXCITITOR-LNM-21-001 | Add VEX observation read endpoints with filters, pagination, RBAC, and tenant scoping. | +| EXCITITOR-LNM-21-202 `Linkset APIs` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-002, EXCITITOR-LNM-21-003 | Implement linkset read/export/evidence endpoints returning correlation/conflict payloads and map errors to `ERR_AGG_*`. | +| EXCITITOR-LNM-21-203 `Event publishing` | TODO | Excititor WebService Guild, Platform Events Guild | EXCITITOR-LNM-21-005 | Publish `vex.linkset.updated` events, document schema, and ensure idempotent delivery. | + +## Graph & Vuln Explorer v1 + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-GRAPH-24-101 `VEX summary API` | TODO | Excititor WebService Guild | EXCITITOR-GRAPH-24-001 | Provide endpoints delivering VEX status summaries per component/asset for Vuln Explorer integration. | +| EXCITITOR-GRAPH-24-102 `Evidence batch API` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-201 | Add batch VEX observation retrieval optimized for Graph overlays/tooltips. | + +## VEX Lens (Sprint 30) + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-VEXLENS-30-001 `VEX evidence enrichers` | TODO | Excititor WebService Guild, VEX Lens Guild | EXCITITOR-VULN-29-001, VEXLENS-30-005 | Include issuer hints, signatures, and product trees in evidence payloads for VEX Lens; Label: VEX-Lens. | + +## Vulnerability Explorer (Sprint 29) + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-VULN-29-001 `VEX key canonicalization` | TODO | Excititor WebService Guild | EXCITITOR-LNM-21-001 | Canonicalize (lossless) VEX advisory/product keys (map to `advisory_key`, capture product scopes); expose original sources in `links[]`; AOC-compliant: no merge, no derived fields, no suppression; backfill existing records. | +| EXCITITOR-VULN-29-002 `Evidence retrieval` | TODO | Excititor WebService Guild | EXCITITOR-VULN-29-001, VULN-API-29-003 | Provide `/vuln/evidence/vex/{advisory_key}` returning raw VEX statements filtered by tenant/product scope for Explorer evidence tabs. | +| EXCITITOR-VULN-29-004 `Observability` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-VULN-29-001 | Add metrics/logs for VEX normalization, suppression scopes, withdrawn statements; emit events consumed by Vuln Explorer resolver. | + +## Advisory AI (Sprint 31) + +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-AIAI-31-001 `Justification enrichment` | TODO | Excititor WebService Guild | EXCITITOR-VULN-29-001 | Expose normalized VEX justifications, product trees, and paragraph anchors for Advisory AI conflict explanations. | +| EXCITITOR-AIAI-31-002 `VEX chunk API` | TODO | Excititor WebService Guild | EXCITITOR-AIAI-31-001, VEXLENS-30-006 | Provide `/vex/evidence/chunks` endpoint returning tenant-scoped VEX statements with signature metadata and scope scores for RAG. | +| EXCITITOR-AIAI-31-003 `Telemetry` | TODO | Excititor WebService Guild, Observability Guild | EXCITITOR-AIAI-31-001 | Emit metrics/logs for VEX chunk usage, signature verification failures, and guardrail triggers. | + +## Observability & Forensics (Epic 15) +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-WEB-OBS-50-001 `Telemetry adoption` | TODO | Excititor WebService Guild | TELEMETRY-OBS-50-001, EXCITITOR-OBS-50-001 | Adopt telemetry core for VEX APIs, ensure responses include trace IDs & correlation headers, and update structured logging for read endpoints. | +| EXCITITOR-WEB-OBS-51-001 `Observability health endpoints` | TODO | Excititor WebService Guild | EXCITITOR-WEB-OBS-50-001, WEB-OBS-51-001 | Implement `/obs/excititor/health` summarizing ingest/link SLOs, signature failure counts, and conflict trends for Console dashboards. | +| EXCITITOR-WEB-OBS-52-001 `Timeline streaming` | TODO | Excititor WebService Guild | EXCITITOR-WEB-OBS-50-001, TIMELINE-OBS-52-003 | Provide SSE bridge for VEX timeline events with tenant filters, pagination, and guardrails. | +| EXCITITOR-WEB-OBS-53-001 `Evidence APIs` | TODO | Excititor WebService Guild, Evidence Locker Guild | EXCITITOR-OBS-53-001, EVID-OBS-53-003 | Expose `/evidence/vex/*` endpoints that fetch locker bundles, enforce scopes, and surface verification metadata. | +| EXCITITOR-WEB-OBS-54-001 `Attestation APIs` | TODO | Excititor WebService Guild | EXCITITOR-OBS-54-001, PROV-OBS-54-001 | Add `/attestations/vex/*` endpoints returning DSSE verification state, builder identity, and chain-of-custody links. | +| EXCITITOR-WEB-OBS-55-001 `Incident mode toggles` | TODO | Excititor WebService Guild, DevOps Guild | EXCITITOR-OBS-55-001, WEB-OBS-55-001 | Provide incident mode API for VEX pipelines with activation audit logs and retention override previews. | + +## Air-Gapped Mode (Epic 16) +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-WEB-AIRGAP-56-001 | TODO | Excititor WebService Guild | AIRGAP-IMP-58-001, EXCITITOR-AIRGAP-56-001 | Support mirror bundle registration via APIs, expose bundle provenance in VEX responses, and block external connectors in sealed mode. | +| EXCITITOR-WEB-AIRGAP-56-002 | TODO | Excititor WebService Guild, AirGap Time Guild | EXCITITOR-WEB-AIRGAP-56-001, AIRGAP-TIME-58-001 | Return VEX staleness metrics and time anchor info in API responses for Console/CLI use. | +| EXCITITOR-WEB-AIRGAP-57-001 | TODO | Excititor WebService Guild, AirGap Policy Guild | AIRGAP-POL-56-001 | Map sealed-mode violations to standardized error payload with remediation guidance. | +| EXCITITOR-WEB-AIRGAP-58-001 | TODO | Excititor WebService Guild, AirGap Importer Guild | EXCITITOR-WEB-AIRGAP-56-001, TIMELINE-OBS-53-001 | Emit timeline events for VEX bundle imports with bundle ID, scope, and actor metadata. | + +## SDKs & OpenAPI (Epic 17) +| ID | Status | Owner(s) | Depends on | Notes | +|----|--------|----------|------------|-------| +| EXCITITOR-WEB-OAS-61-001 | TODO | Excititor WebService Guild | OAS-61-001 | Implement `/.well-known/openapi` discovery endpoint with spec version metadata. | +| EXCITITOR-WEB-OAS-61-002 | TODO | Excititor WebService Guild | APIGOV-61-001 | Standardize error envelope responses and update controller/unit tests. | +| EXCITITOR-WEB-OAS-62-001 | TODO | Excititor WebService Guild | EXCITITOR-OAS-61-002 | Add curated examples for VEX observation/linkset endpoints and ensure portal displays them. | +| EXCITITOR-WEB-OAS-63-001 | TODO | Excititor WebService Guild, API Governance Guild | APIGOV-63-001 | Emit deprecation headers and update docs for retiring VEX APIs. | diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md index bf41b6aa..07d8a1bc 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md @@ -1,9 +1,9 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-ATTEST-01-001 – In-toto predicate & DSSE builder|Team Excititor Attestation|EXCITITOR-CORE-01-001|**DONE (2025-10-16)** – Added deterministic in-toto predicate/statement models, DSSE envelope builder wired to signer abstraction, and attestation client producing metadata + diagnostics.| -|EXCITITOR-ATTEST-01-002 – Rekor v2 client integration|Team Excititor Attestation|EXCITITOR-ATTEST-01-001|**DONE (2025-10-16)** – Implemented Rekor HTTP client with retry/backoff, transparency log abstraction, DI helpers, and attestation client integration capturing Rekor metadata + diagnostics.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-ATTEST-01-001 – In-toto predicate & DSSE builder|Team Excititor Attestation|EXCITITOR-CORE-01-001|**DONE (2025-10-16)** – Added deterministic in-toto predicate/statement models, DSSE envelope builder wired to signer abstraction, and attestation client producing metadata + diagnostics.| +|EXCITITOR-ATTEST-01-002 – Rekor v2 client integration|Team Excititor Attestation|EXCITITOR-ATTEST-01-001|**DONE (2025-10-16)** – Implemented Rekor HTTP client with retry/backoff, transparency log abstraction, DI helpers, and attestation client integration capturing Rekor metadata + diagnostics.| |EXCITITOR-ATTEST-01-003 – Verification suite & observability|Team Excititor Attestation|EXCITITOR-ATTEST-01-002|DOING (2025-10-22) – Continuing implementation: build `IVexAttestationVerifier`, wire metrics/logging, and add regression tests. Draft plan in `EXCITITOR-ATTEST-01-003-plan.md` (2025-10-19) guides scope; updating with worknotes as progress lands.| > Remark (2025-10-22): Added verifier implementation + metrics/tests; next steps include wiring into WebService/Worker flows and expanding negative-path coverage. diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/TASKS.md index a25d1b10..726652a5 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Abstractions/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-ABS-01-001 – Connector context & base classes|Team Excititor Connectors|EXCITITOR-CORE-01-003|**DONE (2025-10-17)** – Added `StellaOps.Excititor.Connectors.Abstractions` project with `VexConnectorBase`, deterministic logging scopes, metadata builder helpers, and connector descriptors; docs updated to highlight the shared abstractions.| -|EXCITITOR-CONN-ABS-01-002 – YAML options & validation|Team Excititor Connectors|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Delivered `VexConnectorOptionsBinder` + binder options/validators, environment-variable expansion, data-annotation checks, and custom validation hooks with documentation updates covering the workflow.| -|EXCITITOR-CONN-ABS-01-003 – Plugin packaging & docs|Team Excititor Connectors|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Authored `docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md`, added quick-start template under `docs/dev/templates/excititor-connector/`, and updated module docs to reference the packaging workflow.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-ABS-01-001 – Connector context & base classes|Team Excititor Connectors|EXCITITOR-CORE-01-003|**DONE (2025-10-17)** – Added `StellaOps.Excititor.Connectors.Abstractions` project with `VexConnectorBase`, deterministic logging scopes, metadata builder helpers, and connector descriptors; docs updated to highlight the shared abstractions.| +|EXCITITOR-CONN-ABS-01-002 – YAML options & validation|Team Excititor Connectors|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Delivered `VexConnectorOptionsBinder` + binder options/validators, environment-variable expansion, data-annotation checks, and custom validation hooks with documentation updates covering the workflow.| +|EXCITITOR-CONN-ABS-01-003 – Plugin packaging & docs|Team Excititor Connectors|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Authored `docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md`, added quick-start template under `docs/dev/templates/excititor-connector/`, and updated module docs to reference the packaging workflow.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Cisco.CSAF/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Cisco.CSAF/TASKS.md index ae214bb6..b02f1afb 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Cisco.CSAF/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Cisco.CSAF/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-CISCO-01-001 – Endpoint discovery & auth plumbing|Team Excititor Connectors – Cisco|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added `CiscoProviderMetadataLoader` with bearer token support, offline snapshot fallback, DI helpers, and tests covering network/offline discovery to unblock subsequent fetch work.| -|EXCITITOR-CONN-CISCO-01-002 – CSAF pull loop & pagination|Team Excititor Connectors – Cisco|EXCITITOR-CONN-CISCO-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Implemented paginated advisory fetch using provider directories, raw document persistence with dedupe/state tracking, offline resiliency, and unit coverage.| -|EXCITITOR-CONN-CISCO-01-003 – Provider trust metadata|Team Excititor Connectors – Cisco|EXCITITOR-CONN-CISCO-01-002, EXCITITOR-POLICY-01-001|**DOING (2025-10-19)** – Prereqs confirmed (both DONE); implementing cosign/PGP trust metadata emission and advisory provenance hints for policy weighting.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-CISCO-01-001 – Endpoint discovery & auth plumbing|Team Excititor Connectors – Cisco|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added `CiscoProviderMetadataLoader` with bearer token support, offline snapshot fallback, DI helpers, and tests covering network/offline discovery to unblock subsequent fetch work.| +|EXCITITOR-CONN-CISCO-01-002 – CSAF pull loop & pagination|Team Excititor Connectors – Cisco|EXCITITOR-CONN-CISCO-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Implemented paginated advisory fetch using provider directories, raw document persistence with dedupe/state tracking, offline resiliency, and unit coverage.| +|EXCITITOR-CONN-CISCO-01-003 – Provider trust metadata|Team Excititor Connectors – Cisco|EXCITITOR-CONN-CISCO-01-002, EXCITITOR-POLICY-01-001|**DOING (2025-10-19)** – Prereqs confirmed (both DONE); implementing cosign/PGP trust metadata emission and advisory provenance hints for policy weighting.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.MSRC.CSAF/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.MSRC.CSAF/TASKS.md index ac9a9094..7f7b70f3 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.MSRC.CSAF/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.MSRC.CSAF/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-MS-01-001 – AAD onboarding & token cache|Team Excititor Connectors – MSRC|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added MSRC connector project with configurable AAD options, token provider (offline/online modes), DI wiring, and unit tests covering caching and fallback scenarios.| -|EXCITITOR-CONN-MS-01-002 – CSAF download pipeline|Team Excititor Connectors – MSRC|EXCITITOR-CONN-MS-01-001, EXCITITOR-STORAGE-01-003|**DOING (2025-10-19)** – Prereqs verified (EXCITITOR-CONN-MS-01-001, EXCITITOR-STORAGE-01-003); drafting fetch/retry plan and storage wiring before implementation of CSAF package download, checksum validation, and quarantine flows.| -|EXCITITOR-CONN-MS-01-003 – Trust metadata & provenance hints|Team Excititor Connectors – MSRC|EXCITITOR-CONN-MS-01-002, EXCITITOR-POLICY-01-001|TODO – Emit cosign/AAD issuer metadata, attach provenance details, and document policy integration.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-MS-01-001 – AAD onboarding & token cache|Team Excititor Connectors – MSRC|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added MSRC connector project with configurable AAD options, token provider (offline/online modes), DI wiring, and unit tests covering caching and fallback scenarios.| +|EXCITITOR-CONN-MS-01-002 – CSAF download pipeline|Team Excititor Connectors – MSRC|EXCITITOR-CONN-MS-01-001, EXCITITOR-STORAGE-01-003|**DOING (2025-10-19)** – Prereqs verified (EXCITITOR-CONN-MS-01-001, EXCITITOR-STORAGE-01-003); drafting fetch/retry plan and storage wiring before implementation of CSAF package download, checksum validation, and quarantine flows.| +|EXCITITOR-CONN-MS-01-003 – Trust metadata & provenance hints|Team Excititor Connectors – MSRC|EXCITITOR-CONN-MS-01-002, EXCITITOR-POLICY-01-001|TODO – Emit cosign/AAD issuer metadata, attach provenance details, and document policy integration.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.OCI.OpenVEX.Attest/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.OCI.OpenVEX.Attest/TASKS.md index 5bd99b10..1d818756 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.OCI.OpenVEX.Attest/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.OCI.OpenVEX.Attest/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-OCI-01-001 – OCI discovery & auth plumbing|Team Excititor Connectors – OCI|EXCITITOR-CONN-ABS-01-001|DONE (2025-10-18) – Added connector skeleton, options/validators, discovery caching, cosign/auth descriptors, offline bundle resolution, DI wiring, and regression tests.| -|EXCITITOR-CONN-OCI-01-002 – Attestation fetch & verify loop|Team Excititor Connectors – OCI|EXCITITOR-CONN-OCI-01-001, EXCITITOR-ATTEST-01-002|DONE (2025-10-18) – Added offline/registry fetch services, DSSE retrieval with retries, signature verification callout, and raw persistence coverage.| -|EXCITITOR-CONN-OCI-01-003 – Provenance metadata & policy hooks|Team Excititor Connectors – OCI|EXCITITOR-CONN-OCI-01-002, EXCITITOR-POLICY-01-001|DONE (2025-10-18) – Enriched attestation metadata with provenance hints, cosign expectations, registry auth context, and signature diagnostics for policy consumption.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-OCI-01-001 – OCI discovery & auth plumbing|Team Excititor Connectors – OCI|EXCITITOR-CONN-ABS-01-001|DONE (2025-10-18) – Added connector skeleton, options/validators, discovery caching, cosign/auth descriptors, offline bundle resolution, DI wiring, and regression tests.| +|EXCITITOR-CONN-OCI-01-002 – Attestation fetch & verify loop|Team Excititor Connectors – OCI|EXCITITOR-CONN-OCI-01-001, EXCITITOR-ATTEST-01-002|DONE (2025-10-18) – Added offline/registry fetch services, DSSE retrieval with retries, signature verification callout, and raw persistence coverage.| +|EXCITITOR-CONN-OCI-01-003 – Provenance metadata & policy hooks|Team Excititor Connectors – OCI|EXCITITOR-CONN-OCI-01-002, EXCITITOR-POLICY-01-001|DONE (2025-10-18) – Enriched attestation metadata with provenance hints, cosign expectations, registry auth context, and signature diagnostics for policy consumption.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Oracle.CSAF/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Oracle.CSAF/TASKS.md index d7a04609..a23205b3 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Oracle.CSAF/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Oracle.CSAF/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-ORACLE-01-001 – Oracle CSAF catalogue discovery|Team Excititor Connectors – Oracle|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-19)** – Implemented cached Oracle CSAF catalog loader with CPU calendar merge, offline snapshot ingest/persist, options validation + DI wiring, and regression tests; prerequisite EXCITITOR-CONN-ABS-01-001 verified DONE per Sprint 5 log (2025-10-19).| -|EXCITITOR-CONN-ORACLE-01-002 – CSAF download & dedupe pipeline|Team Excititor Connectors – Oracle|EXCITITOR-CONN-ORACLE-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-19)** – Added Oracle CSAF fetch loop with retry/backoff, checksum validation, resume-aware state persistence, digest dedupe, configurable throttling, and raw storage wiring; regression tests cover new ingestion and mismatch handling.| -|EXCITITOR-CONN-ORACLE-01-003 – Trust metadata + provenance|Team Excititor Connectors – Oracle|EXCITITOR-CONN-ORACLE-01-002, EXCITITOR-POLICY-01-001|TODO – Emit Oracle signing metadata (PGP/cosign) and provenance hints for consensus weighting.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-ORACLE-01-001 – Oracle CSAF catalogue discovery|Team Excititor Connectors – Oracle|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-19)** – Implemented cached Oracle CSAF catalog loader with CPU calendar merge, offline snapshot ingest/persist, options validation + DI wiring, and regression tests; prerequisite EXCITITOR-CONN-ABS-01-001 verified DONE per Sprint 5 log (2025-10-19).| +|EXCITITOR-CONN-ORACLE-01-002 – CSAF download & dedupe pipeline|Team Excititor Connectors – Oracle|EXCITITOR-CONN-ORACLE-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-19)** – Added Oracle CSAF fetch loop with retry/backoff, checksum validation, resume-aware state persistence, digest dedupe, configurable throttling, and raw storage wiring; regression tests cover new ingestion and mismatch handling.| +|EXCITITOR-CONN-ORACLE-01-003 – Trust metadata + provenance|Team Excititor Connectors – Oracle|EXCITITOR-CONN-ORACLE-01-002, EXCITITOR-POLICY-01-001|TODO – Emit Oracle signing metadata (PGP/cosign) and provenance hints for consensus weighting.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.RedHat.CSAF/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.RedHat.CSAF/TASKS.md index f200e26c..e04572ce 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.RedHat.CSAF/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.RedHat.CSAF/TASKS.md @@ -1,10 +1,10 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-RH-01-001 – Provider metadata discovery|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added `RedHatProviderMetadataLoader` with HTTP/ETag caching, offline snapshot handling, and validation; exposed DI helper + tests covering live, cached, and offline scenarios.| -|EXCITITOR-CONN-RH-01-002 – Incremental CSAF pulls|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Implemented `RedHatCsafConnector` with ROLIE feed parsing, incremental filtering via `context.Since`, CSAF document download + metadata capture, and persistence through `IVexRawDocumentSink`; tests cover live fetch/cache/offline scenarios with ETag handling.| -|EXCITITOR-CONN-RH-01-003 – Trust metadata emission|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002, EXCITITOR-POLICY-01-001|**DONE (2025-10-17)** – Provider metadata loader now emits trust overrides (weight, cosign issuer/pattern, PGP fingerprints) and the connector surfaces provenance hints for policy/consensus layers.| -|EXCITITOR-CONN-RH-01-004 – Resume state persistence|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Connector now loads/saves resume state via `IVexConnectorStateRepository`, tracking last update timestamp and recent document digests to avoid duplicate CSAF ingestion; regression covers state persistence and duplicate skips.| -|EXCITITOR-CONN-RH-01-005 – Worker/WebService integration|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002|**DONE (2025-10-17)** – Worker/WebService now call `AddRedHatCsafConnector`, register the connector + state repo, and default worker scheduling adds the `excititor:redhat` provider so background jobs and orchestration can activate the connector without extra wiring.| -|EXCITITOR-CONN-RH-01-006 – CSAF normalization parity tests|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002, EXCITITOR-FMT-CSAF-01-001|**DONE (2025-10-17)** – Added RHSA fixture-driven regression verifying CSAF normalizer retains Red Hat product metadata, tracking fields, and timestamps (`rhsa-sample.json` + `CsafNormalizerTests.NormalizeAsync_PreservesRedHatSpecificMetadata`).| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-RH-01-001 – Provider metadata discovery|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added `RedHatProviderMetadataLoader` with HTTP/ETag caching, offline snapshot handling, and validation; exposed DI helper + tests covering live, cached, and offline scenarios.| +|EXCITITOR-CONN-RH-01-002 – Incremental CSAF pulls|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Implemented `RedHatCsafConnector` with ROLIE feed parsing, incremental filtering via `context.Since`, CSAF document download + metadata capture, and persistence through `IVexRawDocumentSink`; tests cover live fetch/cache/offline scenarios with ETag handling.| +|EXCITITOR-CONN-RH-01-003 – Trust metadata emission|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002, EXCITITOR-POLICY-01-001|**DONE (2025-10-17)** – Provider metadata loader now emits trust overrides (weight, cosign issuer/pattern, PGP fingerprints) and the connector surfaces provenance hints for policy/consensus layers.| +|EXCITITOR-CONN-RH-01-004 – Resume state persistence|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002, EXCITITOR-STORAGE-01-003|**DONE (2025-10-17)** – Connector now loads/saves resume state via `IVexConnectorStateRepository`, tracking last update timestamp and recent document digests to avoid duplicate CSAF ingestion; regression covers state persistence and duplicate skips.| +|EXCITITOR-CONN-RH-01-005 – Worker/WebService integration|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002|**DONE (2025-10-17)** – Worker/WebService now call `AddRedHatCsafConnector`, register the connector + state repo, and default worker scheduling adds the `excititor:redhat` provider so background jobs and orchestration can activate the connector without extra wiring.| +|EXCITITOR-CONN-RH-01-006 – CSAF normalization parity tests|Team Excititor Connectors – Red Hat|EXCITITOR-CONN-RH-01-002, EXCITITOR-FMT-CSAF-01-001|**DONE (2025-10-17)** – Added RHSA fixture-driven regression verifying CSAF normalizer retains Red Hat product metadata, tracking fields, and timestamps (`rhsa-sample.json` + `CsafNormalizerTests.NormalizeAsync_PreservesRedHatSpecificMetadata`).| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.SUSE.RancherVEXHub/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.SUSE.RancherVEXHub/TASKS.md index 56ba1654..8069143b 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.SUSE.RancherVEXHub/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.SUSE.RancherVEXHub/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-SUSE-01-001 – Rancher hub discovery & auth|Team Excititor Connectors – SUSE|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added Rancher hub options/token provider, discovery metadata loader with offline snapshots + caching, connector shell, DI wiring, and unit tests covering network/offline paths.| -|EXCITITOR-CONN-SUSE-01-002 – Checkpointed event ingestion|Team Excititor Connectors – SUSE|EXCITITOR-CONN-SUSE-01-001, EXCITITOR-STORAGE-01-003|**DOING (2025-10-19)** – Process hub events with resume checkpoints, deduplication, and quarantine path for malformed payloads.
2025-10-19: Prereqs EXCITITOR-CONN-SUSE-01-001 & EXCITITOR-STORAGE-01-003 confirmed complete; initiating checkpoint/resume implementation plan.| -|EXCITITOR-CONN-SUSE-01-003 – Trust metadata & policy hints|Team Excititor Connectors – SUSE|EXCITITOR-CONN-SUSE-01-002, EXCITITOR-POLICY-01-001|TODO – Emit provider trust configuration (signers, weight overrides) and attach provenance hints for consensus engine.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-SUSE-01-001 – Rancher hub discovery & auth|Team Excititor Connectors – SUSE|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added Rancher hub options/token provider, discovery metadata loader with offline snapshots + caching, connector shell, DI wiring, and unit tests covering network/offline paths.| +|EXCITITOR-CONN-SUSE-01-002 – Checkpointed event ingestion|Team Excititor Connectors – SUSE|EXCITITOR-CONN-SUSE-01-001, EXCITITOR-STORAGE-01-003|**DOING (2025-10-19)** – Process hub events with resume checkpoints, deduplication, and quarantine path for malformed payloads.
2025-10-19: Prereqs EXCITITOR-CONN-SUSE-01-001 & EXCITITOR-STORAGE-01-003 confirmed complete; initiating checkpoint/resume implementation plan.| +|EXCITITOR-CONN-SUSE-01-003 – Trust metadata & policy hints|Team Excititor Connectors – SUSE|EXCITITOR-CONN-SUSE-01-002, EXCITITOR-POLICY-01-001|TODO – Emit provider trust configuration (signers, weight overrides) and attach provenance hints for consensus engine.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Ubuntu.CSAF/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Ubuntu.CSAF/TASKS.md index 58e6b8e3..3c6c4469 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Ubuntu.CSAF/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Connectors.Ubuntu.CSAF/TASKS.md @@ -1,8 +1,8 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-CONN-UBUNTU-01-001 – Ubuntu CSAF discovery & channels|Team Excititor Connectors – Ubuntu|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added Ubuntu connector project with configurable channel options, catalog loader (network/offline), DI wiring, and discovery unit tests.| -|EXCITITOR-CONN-UBUNTU-01-002 – Incremental fetch & deduplication|Team Excititor Connectors – Ubuntu|EXCITITOR-CONN-UBUNTU-01-001, EXCITITOR-STORAGE-01-003|**DOING (2025-10-19)** – Fetch CSAF bundles with ETag handling, checksum validation, deduplication, and raw persistence.| -|EXCITITOR-CONN-UBUNTU-01-003 – Trust metadata & provenance|Team Excititor Connectors – Ubuntu|EXCITITOR-CONN-UBUNTU-01-002, EXCITITOR-POLICY-01-001|TODO – Emit Ubuntu signing metadata (GPG fingerprints) plus provenance hints for policy weighting and diagnostics.| -> Remark (2025-10-19, EXCITITOR-CONN-UBUNTU-01-002): Prerequisites EXCITITOR-CONN-UBUNTU-01-001 and EXCITITOR-STORAGE-01-003 verified as **DONE**; advancing to DOING per Wave 0 kickoff. +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-CONN-UBUNTU-01-001 – Ubuntu CSAF discovery & channels|Team Excititor Connectors – Ubuntu|EXCITITOR-CONN-ABS-01-001|**DONE (2025-10-17)** – Added Ubuntu connector project with configurable channel options, catalog loader (network/offline), DI wiring, and discovery unit tests.| +|EXCITITOR-CONN-UBUNTU-01-002 – Incremental fetch & deduplication|Team Excititor Connectors – Ubuntu|EXCITITOR-CONN-UBUNTU-01-001, EXCITITOR-STORAGE-01-003|**DOING (2025-10-19)** – Fetch CSAF bundles with ETag handling, checksum validation, deduplication, and raw persistence.| +|EXCITITOR-CONN-UBUNTU-01-003 – Trust metadata & provenance|Team Excititor Connectors – Ubuntu|EXCITITOR-CONN-UBUNTU-01-002, EXCITITOR-POLICY-01-001|TODO – Emit Ubuntu signing metadata (GPG fingerprints) plus provenance hints for policy weighting and diagnostics.| +> Remark (2025-10-19, EXCITITOR-CONN-UBUNTU-01-002): Prerequisites EXCITITOR-CONN-UBUNTU-01-001 and EXCITITOR-STORAGE-01-003 verified as **DONE**; advancing to DOING per Wave 0 kickoff. diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Export/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Export/TASKS.md index 2b3b123b..8070135c 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Export/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Export/TASKS.md @@ -1,11 +1,11 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-EXPORT-01-001 – Export engine orchestration|Team Excititor Export|EXCITITOR-CORE-01-003|DONE (2025-10-15) – Export engine scaffolding with cache lookup, data source hooks, and deterministic manifest emission.| -|EXCITITOR-EXPORT-01-002 – Cache index & eviction hooks|Team Excititor Export|EXCITITOR-EXPORT-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-16)** – Export engine now invalidates cache entries on force refresh, cache services expose prune/invalidate APIs, and storage maintenance trims expired/dangling records with Mongo2Go coverage.| -|EXCITITOR-EXPORT-01-003 – Artifact store adapters|Team Excititor Export|EXCITITOR-EXPORT-01-001|**DONE (2025-10-16)** – Implemented multi-store pipeline with filesystem, S3-compatible, and offline bundle adapters (hash verification + manifest/zip output) plus unit coverage and DI hooks.| -|EXCITITOR-EXPORT-01-004 – Attestation handoff integration|Team Excititor Export|EXCITITOR-EXPORT-01-001, EXCITITOR-ATTEST-01-001|**DONE (2025-10-17)** – Export engine now invokes attestation client, logs diagnostics, and persists Rekor/envelope metadata on manifests; regression coverage added in `ExportEngineTests.ExportAsync_AttachesAttestationMetadata`.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-EXPORT-01-001 – Export engine orchestration|Team Excititor Export|EXCITITOR-CORE-01-003|DONE (2025-10-15) – Export engine scaffolding with cache lookup, data source hooks, and deterministic manifest emission.| +|EXCITITOR-EXPORT-01-002 – Cache index & eviction hooks|Team Excititor Export|EXCITITOR-EXPORT-01-001, EXCITITOR-STORAGE-01-003|**DONE (2025-10-16)** – Export engine now invalidates cache entries on force refresh, cache services expose prune/invalidate APIs, and storage maintenance trims expired/dangling records with Mongo2Go coverage.| +|EXCITITOR-EXPORT-01-003 – Artifact store adapters|Team Excititor Export|EXCITITOR-EXPORT-01-001|**DONE (2025-10-16)** – Implemented multi-store pipeline with filesystem, S3-compatible, and offline bundle adapters (hash verification + manifest/zip output) plus unit coverage and DI hooks.| +|EXCITITOR-EXPORT-01-004 – Attestation handoff integration|Team Excititor Export|EXCITITOR-EXPORT-01-001, EXCITITOR-ATTEST-01-001|**DONE (2025-10-17)** – Export engine now invokes attestation client, logs diagnostics, and persists Rekor/envelope metadata on manifests; regression coverage added in `ExportEngineTests.ExportAsync_AttachesAttestationMetadata`.| |EXCITITOR-EXPORT-01-005 – Score & resolve envelope surfaces|Team Excititor Export|EXCITITOR-EXPORT-01-004, EXCITITOR-CORE-02-001|**DONE (2025-10-21)** – Export engine now canonicalizes consensus/score envelopes, persists their SHA-256 digests into manifests/attestation metadata, and regression tests validate metadata wiring via `ExportEngineTests`.| |EXCITITOR-EXPORT-01-006 – Quiet provenance packaging|Team Excititor Export|EXCITITOR-EXPORT-01-005, POLICY-CORE-09-005|**DONE (2025-10-21)** – Export manifests now carry quiet-provenance entries (statement digests, signers, justification codes); metadata flows into offline bundles & attestations with regression coverage in `ExportEngineTests`.| |EXCITITOR-EXPORT-01-007 – Mirror bundle + domain manifest|Team Excititor Export|EXCITITOR-EXPORT-01-006|**DONE (2025-10-21)** – Created per-domain mirror bundles with consensus/score artefacts, published signed-ready manifests/index for downstream Excititor sync, and added regression coverage.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CSAF/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CSAF/TASKS.md index 2651c956..40c0b12a 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CSAF/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CSAF/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-FMT-CSAF-01-001 – CSAF normalizer foundation|Team Excititor Formats|EXCITITOR-CORE-01-001|**DONE (2025-10-17)** – Implemented CSAF normalizer + DI hook, parsing tracking metadata, product tree branches/full names, and mapping product statuses into canonical `VexClaim`s with baseline precedence. Regression added in `CsafNormalizerTests`.| -|EXCITITOR-FMT-CSAF-01-002 – Status/justification mapping|Team Excititor Formats|EXCITITOR-FMT-CSAF-01-001, EXCITITOR-POLICY-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-FMT-CSAF-01-001 & EXCITITOR-POLICY-01-001 verified DONE; starting normalization of `product_status`/`justification` values with policy-aligned diagnostics.| -|EXCITITOR-FMT-CSAF-01-003 – CSAF export adapter|Team Excititor Formats|EXCITITOR-EXPORT-01-001, EXCITITOR-FMT-CSAF-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-EXPORT-01-001 & EXCITITOR-FMT-CSAF-01-001 confirmed DONE; drafting deterministic CSAF exporter and manifest metadata flow.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-FMT-CSAF-01-001 – CSAF normalizer foundation|Team Excititor Formats|EXCITITOR-CORE-01-001|**DONE (2025-10-17)** – Implemented CSAF normalizer + DI hook, parsing tracking metadata, product tree branches/full names, and mapping product statuses into canonical `VexClaim`s with baseline precedence. Regression added in `CsafNormalizerTests`.| +|EXCITITOR-FMT-CSAF-01-002 – Status/justification mapping|Team Excititor Formats|EXCITITOR-FMT-CSAF-01-001, EXCITITOR-POLICY-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-FMT-CSAF-01-001 & EXCITITOR-POLICY-01-001 verified DONE; starting normalization of `product_status`/`justification` values with policy-aligned diagnostics.| +|EXCITITOR-FMT-CSAF-01-003 – CSAF export adapter|Team Excititor Formats|EXCITITOR-EXPORT-01-001, EXCITITOR-FMT-CSAF-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-EXPORT-01-001 & EXCITITOR-FMT-CSAF-01-001 confirmed DONE; drafting deterministic CSAF exporter and manifest metadata flow.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CycloneDX/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CycloneDX/TASKS.md index 6b4af5b8..76bfacd2 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CycloneDX/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Formats.CycloneDX/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-FMT-CYCLONE-01-001 – CycloneDX VEX normalizer|Team Excititor Formats|EXCITITOR-CORE-01-001|**DONE (2025-10-17)** – CycloneDX normalizer parses `analysis` data, resolves component references, and emits canonical `VexClaim`s; regression lives in `CycloneDxNormalizerTests`.| -|EXCITITOR-FMT-CYCLONE-01-002 – Component reference reconciliation|Team Excititor Formats|EXCITITOR-FMT-CYCLONE-01-001|**DOING (2025-10-19)** – Prereq EXCITITOR-FMT-CYCLONE-01-001 confirmed DONE; proceeding with reference reconciliation helpers and diagnostics for missing SBOM links.| -|EXCITITOR-FMT-CYCLONE-01-003 – CycloneDX export serializer|Team Excititor Formats|EXCITITOR-EXPORT-01-001, EXCITITOR-FMT-CYCLONE-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-EXPORT-01-001 & EXCITITOR-FMT-CYCLONE-01-001 verified DONE; initiating deterministic CycloneDX VEX exporter work.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-FMT-CYCLONE-01-001 – CycloneDX VEX normalizer|Team Excititor Formats|EXCITITOR-CORE-01-001|**DONE (2025-10-17)** – CycloneDX normalizer parses `analysis` data, resolves component references, and emits canonical `VexClaim`s; regression lives in `CycloneDxNormalizerTests`.| +|EXCITITOR-FMT-CYCLONE-01-002 – Component reference reconciliation|Team Excititor Formats|EXCITITOR-FMT-CYCLONE-01-001|**DOING (2025-10-19)** – Prereq EXCITITOR-FMT-CYCLONE-01-001 confirmed DONE; proceeding with reference reconciliation helpers and diagnostics for missing SBOM links.| +|EXCITITOR-FMT-CYCLONE-01-003 – CycloneDX export serializer|Team Excititor Formats|EXCITITOR-EXPORT-01-001, EXCITITOR-FMT-CYCLONE-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-EXPORT-01-001 & EXCITITOR-FMT-CYCLONE-01-001 verified DONE; initiating deterministic CycloneDX VEX exporter work.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Formats.OpenVEX/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Formats.OpenVEX/TASKS.md index 8502c87f..d736ca08 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Formats.OpenVEX/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Formats.OpenVEX/TASKS.md @@ -1,7 +1,7 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). -# TASKS -| Task | Owner(s) | Depends on | Notes | -|---|---|---|---| -|EXCITITOR-FMT-OPENVEX-01-001 – OpenVEX normalizer|Team Excititor Formats|EXCITITOR-CORE-01-001|**DONE (2025-10-17)** – OpenVEX normalizer parses statements/products, maps status/justification, and surfaces provenance metadata; coverage in `OpenVexNormalizerTests`.| -|EXCITITOR-FMT-OPENVEX-01-002 – Statement merge utilities|Team Excititor Formats|EXCITITOR-FMT-OPENVEX-01-001|**DOING (2025-10-19)** – Prereq EXCITITOR-FMT-OPENVEX-01-001 confirmed DONE; building deterministic merge reducers with policy diagnostics.| -|EXCITITOR-FMT-OPENVEX-01-003 – OpenVEX export writer|Team Excititor Formats|EXCITITOR-EXPORT-01-001, EXCITITOR-FMT-OPENVEX-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-EXPORT-01-001 & EXCITITOR-FMT-OPENVEX-01-001 verified DONE; starting canonical OpenVEX exporter with stable ordering/SBOM references.| +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). +# TASKS +| Task | Owner(s) | Depends on | Notes | +|---|---|---|---| +|EXCITITOR-FMT-OPENVEX-01-001 – OpenVEX normalizer|Team Excititor Formats|EXCITITOR-CORE-01-001|**DONE (2025-10-17)** – OpenVEX normalizer parses statements/products, maps status/justification, and surfaces provenance metadata; coverage in `OpenVexNormalizerTests`.| +|EXCITITOR-FMT-OPENVEX-01-002 – Statement merge utilities|Team Excititor Formats|EXCITITOR-FMT-OPENVEX-01-001|**DOING (2025-10-19)** – Prereq EXCITITOR-FMT-OPENVEX-01-001 confirmed DONE; building deterministic merge reducers with policy diagnostics.| +|EXCITITOR-FMT-OPENVEX-01-003 – OpenVEX export writer|Team Excititor Formats|EXCITITOR-EXPORT-01-001, EXCITITOR-FMT-OPENVEX-01-001|**DOING (2025-10-19)** – Prereqs EXCITITOR-EXPORT-01-001 & EXCITITOR-FMT-OPENVEX-01-001 verified DONE; starting canonical OpenVEX exporter with stable ordering/SBOM references.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Policy/TASKS.md b/src/Excititor/__Libraries/StellaOps.Excititor.Policy/TASKS.md index 4256ff27..438f68fe 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Policy/TASKS.md +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Policy/TASKS.md @@ -1,11 +1,11 @@ -If you are working on this file you need to read docs/ARCHITECTURE_EXCITITOR.md and ./AGENTS.md). +If you are working on this file you need to read docs/modules/excititor/ARCHITECTURE.md and ./AGENTS.md). # TASKS | Task | Owner(s) | Depends on | Notes | |---|---|---|---| |EXCITITOR-POLICY-01-001 – Policy schema & binding|Team Excititor Policy|EXCITITOR-CORE-01-001|DONE (2025-10-15) – Established `VexPolicyOptions`, options binding, and snapshot provider covering baseline weights/overrides.| |EXCITITOR-POLICY-01-002 – Policy evaluator service|Team Excititor Policy|EXCITITOR-POLICY-01-001|DONE (2025-10-15) – `VexPolicyEvaluator` exposes immutable snapshots to consensus and normalizes rejection reasons.| -|EXCITITOR-POLICY-01-003 – Operator diagnostics & docs|Team Excititor Policy|EXCITITOR-POLICY-01-001|**DONE (2025-10-16)** – Surface structured diagnostics (CLI/WebService) and author policy upgrade guidance in docs/ARCHITECTURE_EXCITITOR.md appendix.
2025-10-16: Added `IVexPolicyDiagnostics`/`VexPolicyDiagnosticsReport`, sorted issue ordering, recommendations, and appendix guidance. Tests: `dotnet test src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/StellaOps.Excititor.Core.Tests.csproj`.| +|EXCITITOR-POLICY-01-003 – Operator diagnostics & docs|Team Excititor Policy|EXCITITOR-POLICY-01-001|**DONE (2025-10-16)** – Surface structured diagnostics (CLI/WebService) and author policy upgrade guidance in docs/modules/excititor/ARCHITECTURE.md appendix.
2025-10-16: Added `IVexPolicyDiagnostics`/`VexPolicyDiagnosticsReport`, sorted issue ordering, recommendations, and appendix guidance. Tests: `dotnet test src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/StellaOps.Excititor.Core.Tests.csproj`.| |EXCITITOR-POLICY-01-004 – Policy schema validation & YAML binding|Team Excititor Policy|EXCITITOR-POLICY-01-001|**DONE (2025-10-16)** – Added strongly-typed YAML/JSON binding, schema validation, and deterministic diagnostics for operator-supplied policy bundles.| |EXCITITOR-POLICY-01-005 – Policy change tracking & telemetry|Team Excititor Policy|EXCITITOR-POLICY-01-002|**DONE (2025-10-16)** – Emit revision history, expose snapshot digests via CLI/WebService, and add structured logging/metrics for policy reloads.
2025-10-16: `VexPolicySnapshot` now carries revision/digest, provider logs reloads, `vex.policy.reloads` metric emitted, binder/diagnostics expose digest metadata. Tests: `dotnet test src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/StellaOps.Excititor.Core.Tests.csproj`.| -|EXCITITOR-POLICY-02-001 – Scoring coefficients & weight ceilings|Team Excititor Policy|EXCITITOR-POLICY-01-004|DONE (2025-10-19) – Added `weights.ceiling` + `scoring.{alpha,beta}` options with normalization warnings, extended consensus policy/digest, refreshed docs (`docs/ARCHITECTURE_EXCITITOR.md`, `docs/EXCITITOR_SCORRING.md`), and validated via `dotnet test` for core/policy suites.| +|EXCITITOR-POLICY-02-001 – Scoring coefficients & weight ceilings|Team Excititor Policy|EXCITITOR-POLICY-01-004|DONE (2025-10-19) – Added `weights.ceiling` + `scoring.{alpha,beta}` options with normalization warnings, extended consensus policy/digest, refreshed docs (`docs/modules/excititor/ARCHITECTURE.md`, `docs/modules/excititor/scoring.md`), and validated via `dotnet test` for core/policy suites.| |EXCITITOR-POLICY-02-002 – Diagnostics for scoring signals|Team Excititor Policy|EXCITITOR-POLICY-02-001|BACKLOG – Update diagnostics reports to surface missing severity/KEV/EPSS mappings, coefficient overrides, and provide actionable recommendations for policy tuning.| diff --git a/src/Excititor/__Libraries/StellaOps.Excititor.Policy/VexPolicyDiagnostics.cs b/src/Excititor/__Libraries/StellaOps.Excititor.Policy/VexPolicyDiagnostics.cs index 2140c5ed..cb5405ef 100644 --- a/src/Excititor/__Libraries/StellaOps.Excititor.Policy/VexPolicyDiagnostics.cs +++ b/src/Excititor/__Libraries/StellaOps.Excititor.Policy/VexPolicyDiagnostics.cs @@ -1,87 +1,87 @@ -using System; -using System.Collections.Immutable; -using System.Linq; - -namespace StellaOps.Excititor.Policy; - -public interface IVexPolicyDiagnostics -{ - VexPolicyDiagnosticsReport GetDiagnostics(); -} - -public sealed record VexPolicyDiagnosticsReport( - string Version, - string RevisionId, - string Digest, - int ErrorCount, - int WarningCount, - DateTimeOffset GeneratedAt, - ImmutableArray Issues, - ImmutableArray Recommendations, - ImmutableDictionary ActiveOverrides); - -public sealed class VexPolicyDiagnostics : IVexPolicyDiagnostics -{ - private readonly IVexPolicyProvider _policyProvider; - private readonly TimeProvider _timeProvider; - - public VexPolicyDiagnostics( - IVexPolicyProvider policyProvider, - TimeProvider? timeProvider = null) - { - _policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider)); - _timeProvider = timeProvider ?? TimeProvider.System; - } - - public VexPolicyDiagnosticsReport GetDiagnostics() - { - var snapshot = _policyProvider.GetSnapshot(); - var issues = snapshot.Issues; - - var errorCount = issues.Count(static issue => issue.Severity == VexPolicyIssueSeverity.Error); - var warningCount = issues.Count(static issue => issue.Severity == VexPolicyIssueSeverity.Warning); - var overrides = snapshot.ConsensusOptions.ProviderOverrides - .OrderBy(static pair => pair.Key, StringComparer.Ordinal) - .ToImmutableDictionary(); - - var recommendations = BuildRecommendations(errorCount, warningCount, overrides); - - return new VexPolicyDiagnosticsReport( - snapshot.Version, - snapshot.RevisionId, - snapshot.Digest, - errorCount, - warningCount, - _timeProvider.GetUtcNow(), - issues, - recommendations, - overrides); - } - - private static ImmutableArray BuildRecommendations( - int errorCount, - int warningCount, - ImmutableDictionary overrides) - { - var messages = ImmutableArray.CreateBuilder(); - - if (errorCount > 0) - { - messages.Add("Resolve policy errors before running consensus; defaults are used while errors persist."); - } - - if (warningCount > 0) - { - messages.Add("Review policy warnings via CLI/Web diagnostics and adjust configuration as needed."); - } - - if (overrides.Count > 0) - { - messages.Add($"Provider overrides active for: {string.Join(", ", overrides.Keys)}."); - } - - messages.Add("Refer to docs/ARCHITECTURE_EXCITITOR.md for policy upgrade and diagnostics guidance."); - - return messages.ToImmutable(); - } -} +using System; +using System.Collections.Immutable; +using System.Linq; + +namespace StellaOps.Excititor.Policy; + +public interface IVexPolicyDiagnostics +{ + VexPolicyDiagnosticsReport GetDiagnostics(); +} + +public sealed record VexPolicyDiagnosticsReport( + string Version, + string RevisionId, + string Digest, + int ErrorCount, + int WarningCount, + DateTimeOffset GeneratedAt, + ImmutableArray Issues, + ImmutableArray Recommendations, + ImmutableDictionary ActiveOverrides); + +public sealed class VexPolicyDiagnostics : IVexPolicyDiagnostics +{ + private readonly IVexPolicyProvider _policyProvider; + private readonly TimeProvider _timeProvider; + + public VexPolicyDiagnostics( + IVexPolicyProvider policyProvider, + TimeProvider? timeProvider = null) + { + _policyProvider = policyProvider ?? throw new ArgumentNullException(nameof(policyProvider)); + _timeProvider = timeProvider ?? TimeProvider.System; + } + + public VexPolicyDiagnosticsReport GetDiagnostics() + { + var snapshot = _policyProvider.GetSnapshot(); + var issues = snapshot.Issues; + + var errorCount = issues.Count(static issue => issue.Severity == VexPolicyIssueSeverity.Error); + var warningCount = issues.Count(static issue => issue.Severity == VexPolicyIssueSeverity.Warning); + var overrides = snapshot.ConsensusOptions.ProviderOverrides + .OrderBy(static pair => pair.Key, StringComparer.Ordinal) + .ToImmutableDictionary(); + + var recommendations = BuildRecommendations(errorCount, warningCount, overrides); + + return new VexPolicyDiagnosticsReport( + snapshot.Version, + snapshot.RevisionId, + snapshot.Digest, + errorCount, + warningCount, + _timeProvider.GetUtcNow(), + issues, + recommendations, + overrides); + } + + private static ImmutableArray BuildRecommendations( + int errorCount, + int warningCount, + ImmutableDictionary overrides) + { + var messages = ImmutableArray.CreateBuilder(); + + if (errorCount > 0) + { + messages.Add("Resolve policy errors before running consensus; defaults are used while errors persist."); + } + + if (warningCount > 0) + { + messages.Add("Review policy warnings via CLI/Web diagnostics and adjust configuration as needed."); + } + + if (overrides.Count > 0) + { + messages.Add($"Provider overrides active for: {string.Join(", ", overrides.Keys)}."); + } + + messages.Add("Refer to docs/modules/excititor/architecture.md for policy upgrade and diagnostics guidance."); + + return messages.ToImmutable(); + } +} diff --git a/src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/VexPolicyDiagnosticsTests.cs b/src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/VexPolicyDiagnosticsTests.cs index 0d86cb9d..31cba8dc 100644 --- a/src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/VexPolicyDiagnosticsTests.cs +++ b/src/Excititor/__Tests/StellaOps.Excititor.Core.Tests/VexPolicyDiagnosticsTests.cs @@ -1,169 +1,169 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Time.Testing; -using StellaOps.Excititor.Core; -using StellaOps.Excititor.Policy; -using System.Diagnostics.Metrics; - -namespace StellaOps.Excititor.Core.Tests; - -public class VexPolicyDiagnosticsTests -{ - [Fact] - public void GetDiagnostics_ReportsCountsRecommendationsAndOverrides() - { - var overrides = new[] - { - new KeyValuePair("provider-a", 0.8), - new KeyValuePair("provider-b", 0.6), - }; - - var snapshot = new VexPolicySnapshot( - "custom/v1", - new VexConsensusPolicyOptions( - version: "custom/v1", - providerOverrides: overrides), - new BaselineVexConsensusPolicy(), - ImmutableArray.Create( - new VexPolicyIssue("sample.error", "Blocking issue.", VexPolicyIssueSeverity.Error), - new VexPolicyIssue("sample.warning", "Non-blocking issue.", VexPolicyIssueSeverity.Warning)), - "rev-test", - "ABCDEF"); - - var fakeProvider = new FakePolicyProvider(snapshot); - var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 16, 17, 0, 0, TimeSpan.Zero)); - var diagnostics = new VexPolicyDiagnostics(fakeProvider, fakeTime); - - var report = diagnostics.GetDiagnostics(); - - Assert.Equal("custom/v1", report.Version); - Assert.Equal("rev-test", report.RevisionId); - Assert.Equal("ABCDEF", report.Digest); - Assert.Equal(1, report.ErrorCount); - Assert.Equal(1, report.WarningCount); - Assert.Equal(fakeTime.GetUtcNow(), report.GeneratedAt); - Assert.Collection(report.Issues, - issue => Assert.Equal("sample.error", issue.Code), - issue => Assert.Equal("sample.warning", issue.Code)); - Assert.Equal(new[] { "provider-a", "provider-b" }, report.ActiveOverrides.Keys.OrderBy(static key => key, StringComparer.Ordinal)); - Assert.Contains(report.Recommendations, message => message.Contains("Resolve policy errors", StringComparison.OrdinalIgnoreCase)); - Assert.Contains(report.Recommendations, message => message.Contains("provider-a", StringComparison.OrdinalIgnoreCase)); - Assert.Contains(report.Recommendations, message => message.Contains("docs/ARCHITECTURE_EXCITITOR.md", StringComparison.OrdinalIgnoreCase)); - } - - [Fact] - public void GetDiagnostics_WhenNoIssues_StillReturnsDefaultRecommendation() - { - var fakeProvider = new FakePolicyProvider(VexPolicySnapshot.Default); - var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 16, 17, 0, 0, TimeSpan.Zero)); - var diagnostics = new VexPolicyDiagnostics(fakeProvider, fakeTime); - - var report = diagnostics.GetDiagnostics(); - - Assert.Equal(0, report.ErrorCount); - Assert.Equal(0, report.WarningCount); - Assert.Empty(report.ActiveOverrides); - Assert.Single(report.Recommendations); - } - - [Fact] - public void PolicyProvider_ComputesRevisionAndDigest_AndEmitsTelemetry() - { - using var listener = new MeterListener(); - var reloadMeasurements = 0; - string? lastRevision = null; - listener.InstrumentPublished += (instrument, _) => - { - if (instrument.Meter.Name == "StellaOps.Excititor.Policy" && - instrument.Name == "vex.policy.reloads") - { - listener.EnableMeasurementEvents(instrument); - } - }; - - listener.SetMeasurementEventCallback((instrument, measurement, tags, state) => - { - reloadMeasurements++; - foreach (var tag in tags) - { - if (tag.Key is "revision" && tag.Value is string revision) - { - lastRevision = revision; - break; - } - } - }); - - listener.Start(); - - var optionsMonitor = new MutableOptionsMonitor(new VexPolicyOptions()); - var provider = new VexPolicyProvider(optionsMonitor, NullLogger.Instance); - - var snapshot1 = provider.GetSnapshot(); - Assert.Equal("rev-1", snapshot1.RevisionId); - Assert.False(string.IsNullOrWhiteSpace(snapshot1.Digest)); - - var snapshot2 = provider.GetSnapshot(); - Assert.Equal("rev-1", snapshot2.RevisionId); - Assert.Equal(snapshot1.Digest, snapshot2.Digest); - - optionsMonitor.Update(new VexPolicyOptions - { - ProviderOverrides = new Dictionary - { - ["provider-a"] = 0.4 - } - }); - - var snapshot3 = provider.GetSnapshot(); - Assert.Equal("rev-2", snapshot3.RevisionId); - Assert.NotEqual(snapshot1.Digest, snapshot3.Digest); - - listener.Dispose(); - - Assert.True(reloadMeasurements >= 2); - Assert.Equal("rev-2", lastRevision); - } - - private sealed class FakePolicyProvider : IVexPolicyProvider - { - private readonly VexPolicySnapshot _snapshot; - - public FakePolicyProvider(VexPolicySnapshot snapshot) - { - _snapshot = snapshot; - } - - public VexPolicySnapshot GetSnapshot() => _snapshot; - } - - private sealed class MutableOptionsMonitor : IOptionsMonitor - { - private T _value; - - public MutableOptionsMonitor(T value) - { - _value = value; - } - - public T CurrentValue => _value; - - public T Get(string? name) => _value; - - public void Update(T newValue) => _value = newValue; - - public IDisposable OnChange(Action listener) => NullDisposable.Instance; - - private sealed class NullDisposable : IDisposable - { - public static readonly NullDisposable Instance = new(); - public void Dispose() - { - } - } - } -} +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Time.Testing; +using StellaOps.Excititor.Core; +using StellaOps.Excititor.Policy; +using System.Diagnostics.Metrics; + +namespace StellaOps.Excititor.Core.Tests; + +public class VexPolicyDiagnosticsTests +{ + [Fact] + public void GetDiagnostics_ReportsCountsRecommendationsAndOverrides() + { + var overrides = new[] + { + new KeyValuePair("provider-a", 0.8), + new KeyValuePair("provider-b", 0.6), + }; + + var snapshot = new VexPolicySnapshot( + "custom/v1", + new VexConsensusPolicyOptions( + version: "custom/v1", + providerOverrides: overrides), + new BaselineVexConsensusPolicy(), + ImmutableArray.Create( + new VexPolicyIssue("sample.error", "Blocking issue.", VexPolicyIssueSeverity.Error), + new VexPolicyIssue("sample.warning", "Non-blocking issue.", VexPolicyIssueSeverity.Warning)), + "rev-test", + "ABCDEF"); + + var fakeProvider = new FakePolicyProvider(snapshot); + var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 16, 17, 0, 0, TimeSpan.Zero)); + var diagnostics = new VexPolicyDiagnostics(fakeProvider, fakeTime); + + var report = diagnostics.GetDiagnostics(); + + Assert.Equal("custom/v1", report.Version); + Assert.Equal("rev-test", report.RevisionId); + Assert.Equal("ABCDEF", report.Digest); + Assert.Equal(1, report.ErrorCount); + Assert.Equal(1, report.WarningCount); + Assert.Equal(fakeTime.GetUtcNow(), report.GeneratedAt); + Assert.Collection(report.Issues, + issue => Assert.Equal("sample.error", issue.Code), + issue => Assert.Equal("sample.warning", issue.Code)); + Assert.Equal(new[] { "provider-a", "provider-b" }, report.ActiveOverrides.Keys.OrderBy(static key => key, StringComparer.Ordinal)); + Assert.Contains(report.Recommendations, message => message.Contains("Resolve policy errors", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(report.Recommendations, message => message.Contains("provider-a", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(report.Recommendations, message => message.Contains("docs/modules/excititor/architecture.md", StringComparison.OrdinalIgnoreCase)); + } + + [Fact] + public void GetDiagnostics_WhenNoIssues_StillReturnsDefaultRecommendation() + { + var fakeProvider = new FakePolicyProvider(VexPolicySnapshot.Default); + var fakeTime = new FakeTimeProvider(new DateTimeOffset(2025, 10, 16, 17, 0, 0, TimeSpan.Zero)); + var diagnostics = new VexPolicyDiagnostics(fakeProvider, fakeTime); + + var report = diagnostics.GetDiagnostics(); + + Assert.Equal(0, report.ErrorCount); + Assert.Equal(0, report.WarningCount); + Assert.Empty(report.ActiveOverrides); + Assert.Single(report.Recommendations); + } + + [Fact] + public void PolicyProvider_ComputesRevisionAndDigest_AndEmitsTelemetry() + { + using var listener = new MeterListener(); + var reloadMeasurements = 0; + string? lastRevision = null; + listener.InstrumentPublished += (instrument, _) => + { + if (instrument.Meter.Name == "StellaOps.Excititor.Policy" && + instrument.Name == "vex.policy.reloads") + { + listener.EnableMeasurementEvents(instrument); + } + }; + + listener.SetMeasurementEventCallback((instrument, measurement, tags, state) => + { + reloadMeasurements++; + foreach (var tag in tags) + { + if (tag.Key is "revision" && tag.Value is string revision) + { + lastRevision = revision; + break; + } + } + }); + + listener.Start(); + + var optionsMonitor = new MutableOptionsMonitor(new VexPolicyOptions()); + var provider = new VexPolicyProvider(optionsMonitor, NullLogger.Instance); + + var snapshot1 = provider.GetSnapshot(); + Assert.Equal("rev-1", snapshot1.RevisionId); + Assert.False(string.IsNullOrWhiteSpace(snapshot1.Digest)); + + var snapshot2 = provider.GetSnapshot(); + Assert.Equal("rev-1", snapshot2.RevisionId); + Assert.Equal(snapshot1.Digest, snapshot2.Digest); + + optionsMonitor.Update(new VexPolicyOptions + { + ProviderOverrides = new Dictionary + { + ["provider-a"] = 0.4 + } + }); + + var snapshot3 = provider.GetSnapshot(); + Assert.Equal("rev-2", snapshot3.RevisionId); + Assert.NotEqual(snapshot1.Digest, snapshot3.Digest); + + listener.Dispose(); + + Assert.True(reloadMeasurements >= 2); + Assert.Equal("rev-2", lastRevision); + } + + private sealed class FakePolicyProvider : IVexPolicyProvider + { + private readonly VexPolicySnapshot _snapshot; + + public FakePolicyProvider(VexPolicySnapshot snapshot) + { + _snapshot = snapshot; + } + + public VexPolicySnapshot GetSnapshot() => _snapshot; + } + + private sealed class MutableOptionsMonitor : IOptionsMonitor + { + private T _value; + + public MutableOptionsMonitor(T value) + { + _value = value; + } + + public T CurrentValue => _value; + + public T Get(string? name) => _value; + + public void Update(T newValue) => _value = newValue; + + public IDisposable OnChange(Action listener) => NullDisposable.Instance; + + private sealed class NullDisposable : IDisposable + { + public static readonly NullDisposable Instance = new(); + public void Dispose() + { + } + } + } +} diff --git a/src/ExportCenter/StellaOps.ExportCenter.AttestationBundles/TASKS.md b/src/ExportCenter/StellaOps.ExportCenter.AttestationBundles/TASKS.md index e6bb4760..b67d192a 100644 --- a/src/ExportCenter/StellaOps.ExportCenter.AttestationBundles/TASKS.md +++ b/src/ExportCenter/StellaOps.ExportCenter.AttestationBundles/TASKS.md @@ -10,4 +10,4 @@ | ID | Status | Owner(s) | Depends on | Description | Exit Criteria | |----|--------|----------|------------|-------------|---------------| | EXPORT-ATTEST-75-001 | TODO | Attestation Bundle Guild, CLI Attestor Guild | EXPORT-ATTEST-74-001 | Provide CLI command `stella attest bundle verify/import` for air-gap usage. | CLI verifies/signatures; import seeds attestor store; tests cover corrupted bundle. | -| EXPORT-ATTEST-75-002 | TODO | Attestation Bundle Guild, Docs Guild | EXPORT-ATTEST-75-001 | Document `/docs/attestor/airgap.md` with bundle workflows and verification steps. | Doc merged with banner; examples verified. | +| EXPORT-ATTEST-75-002 | TODO | Attestation Bundle Guild, Docs Guild | EXPORT-ATTEST-75-001 | Document `/docs/modules/attestor/airgap.md` with bundle workflows and verification steps. | Doc merged with banner; examples verified. | diff --git a/src/FASTER_MODELING_AND_NORMALIZATION.md b/src/FASTER_MODELING_AND_NORMALIZATION.md deleted file mode 100644 index 59a9eb19..00000000 --- a/src/FASTER_MODELING_AND_NORMALIZATION.md +++ /dev/null @@ -1,140 +0,0 @@ -Here’s a quick, practical idea to make your version-range modeling cleaner and faster to query. - -![A simple diagram showing a Vulnerability doc with an embedded normalizedVersions array next to a pipeline icon labeled “simpler aggregations”.](https://images.unsplash.com/photo-1515879218367-8466d910aaa4?q=80\&w=1470\&auto=format\&fit=crop) - -# Rethinking `SemVerRangeBuilder` + MongoDB - -**Problem (today):** Version normalization rules live as a nested object (and often as a bespoke structure per source). This can force awkward `$objectToArray`, `$map`, and conditional logic in pipelines when you need to: - -* match “is version X affected?” -* flatten ranges for analytics -* de-duplicate across sources - -**Proposal:** Store *normalized version rules as an embedded collection (array of small docs)* instead of a single nested object. - -## Minimal background - -* **SemVer normalization**: converting all source-specific version notations into a single, strict representation (e.g., `>=1.2.3 <2.0.0`, exact pins, wildcards). -* **Embedded collection**: an array of consistently shaped items inside the parent doc—great for `$unwind`-centric analytics and direct matches. - -## Suggested shape - -```json -{ - "_id": "VULN-123", - "packageId": "pkg:npm/lodash", - "source": "NVD", - "normalizedVersions": [ - { - "scheme": "semver", - "type": "range", // "range" | "exact" | "lt" | "lte" | "gt" | "gte" - "min": "1.2.3", // optional - "minInclusive": true, // optional - "max": "2.0.0", // optional - "maxInclusive": false, // optional - "notes": "from GHSA GHSA-xxxx" // traceability - }, - { - "scheme": "semver", - "type": "exact", - "value": "1.5.0" - } - ], - "metadata": { "ingestedAt": "2025-10-10T12:00:00Z" } -} -``` - -### Why this helps - -* **Simpler queries** - - * *Is v affected?* - - ```js - db.vulns.aggregate([ - { $match: { packageId: "pkg:npm/lodash" } }, - { $unwind: "$normalizedVersions" }, - { $match: { - $or: [ - { "normalizedVersions.type": "exact", "normalizedVersions.value": "1.5.0" }, - { "normalizedVersions.type": "range", - "normalizedVersions.min": { $lte: "1.5.0" }, - "normalizedVersions.max": { $gt: "1.5.0" } } - ] - }}, - { $project: { _id: 1 } } - ]) - ``` - * No `$objectToArray`, fewer `$cond`s. - -* **Cheaper storage** - - * Arrays of tiny docs compress well and avoid wide nested structures with many nulls/keys. - -* **Easier dedup/merge** - - * `$unwind` → normalize → `$group` by `{scheme,type,min,max,value}` to collapse equivalent rules across sources. - -## Builder changes (`SemVerRangeBuilder`) - -* **Emit items, not a monolith**: have the builder return `IEnumerable`. -* **Normalize early**: resolve “aliases” (`1.2.x`, `^1.2.3`, distro styles) into canonical `(type,min,max,…)` before persistence. -* **Traceability**: include `notes`/`sourceRef` on each rule so you can re-materialize provenance during audits. -* **Lean projection helper**: when you only need normalized rules (and not the intermediate primitives), prefer `SemVerRangeRuleBuilder.BuildNormalizedRules(rawRange, patchedVersion, provenanceNote)` to skip manual projections. - -### C# sketch - -```csharp -public record NormalizedVersionRule( - string Scheme, // "semver" - string Type, // "range" | "exact" | ... - string? Min = null, - bool? MinInclusive = null, - string? Max = null, - bool? MaxInclusive = null, - string? Value = null, - string? Notes = null -); - -public static class SemVerRangeBuilder -{ - public static IEnumerable Build(string raw) - { - // parse raw (^1.2.3, 1.2.x, <=2.0.0, etc.) - // yield canonical rules: - yield return new NormalizedVersionRule( - Scheme: "semver", - Type: "range", - Min: "1.2.3", - MinInclusive: true, - Max: "2.0.0", - MaxInclusive: false, - Notes: "nvd:ABC-123" - ); - } -} -``` - -## Aggregation patterns you unlock - -* **Fast “affected version” lookups** via `$unwind + $match` (can complement with a computed sort key). -* **Rollups**: count of vulns per `(major,minor)` by mapping each rule into bucketed segments. -* **Cross-source reconciliation**: group identical rules to de-duplicate. - -## Indexing tips - -* Compound index on `{ packageId: 1, "normalizedVersions.scheme": 1, "normalizedVersions.type": 1 }`. -* If lookups by exact value are common: add a sparse index on `"normalizedVersions.value"`. - -## Migration path (safe + incremental) - -1. **Dual-write**: keep old nested object while writing the new `normalizedVersions` array. -2. **Backfill** existing docs with a one-time script using your current builder. -3. **Cutover** queries/aggregations to the new path (behind a feature flag). -4. **Clean up** old field after soak. - -If you want, I can draft: - -* a one-time Mongo backfill script, -* the new EF/Mongo C# POCOs, and -* a test matrix (edge cases: prerelease tags, build metadata, `0.*` semantics, distro-style ranges). diff --git a/src/Notify/StellaOps.Notify.WebService/AGENTS.md b/src/Notify/StellaOps.Notify.WebService/AGENTS.md index 7ff7827b..b833a9e8 100644 --- a/src/Notify/StellaOps.Notify.WebService/AGENTS.md +++ b/src/Notify/StellaOps.Notify.WebService/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.WebService — Agent Charter - -## Mission -Implement Notify control plane per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.WebService — Agent Charter + +## Mission +Implement Notify control plane per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/StellaOps.Notify.Worker/AGENTS.md b/src/Notify/StellaOps.Notify.Worker/AGENTS.md index 6ce16fe6..949f7254 100644 --- a/src/Notify/StellaOps.Notify.Worker/AGENTS.md +++ b/src/Notify/StellaOps.Notify.Worker/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Worker — Agent Charter - -## Mission -Consume events, evaluate rules, and dispatch deliveries per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Worker — Agent Charter + +## Mission +Consume events, evaluate rules, and dispatch deliveries per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Email/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Email/AGENTS.md index c85e6afe..690194ce 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Email/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Email/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Connectors.Email — Agent Charter - -## Mission -Implement SMTP connector plug-in per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Connectors.Email — Agent Charter + +## Mission +Implement SMTP connector plug-in per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Slack/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Slack/AGENTS.md index 1829cf9a..bf1b6173 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Slack/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Slack/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Connectors.Slack — Agent Charter - -## Mission -Deliver Slack connector plug-in per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Connectors.Slack — Agent Charter + +## Mission +Deliver Slack connector plug-in per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Teams/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Teams/AGENTS.md index ad1102e6..04348aa2 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Teams/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Teams/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Connectors.Teams — Agent Charter - -## Mission -Implement Microsoft Teams connector plug-in per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Connectors.Teams — Agent Charter + +## Mission +Implement Microsoft Teams connector plug-in per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Webhook/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Webhook/AGENTS.md index 04a6541a..77f27cb7 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Connectors.Webhook/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Connectors.Webhook/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Connectors.Webhook — Agent Charter - -## Mission -Implement generic webhook connector plug-in per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Connectors.Webhook — Agent Charter + +## Mission +Implement generic webhook connector plug-in per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Engine/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Engine/AGENTS.md index b9598a95..c377a902 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Engine/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Engine/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Engine — Agent Charter - -## Mission -Deliver rule evaluation, digest, and rendering logic per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Engine — Agent Charter + +## Mission +Deliver rule evaluation, digest, and rendering logic per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Models/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Models/AGENTS.md index a7935047..7d98246c 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Models/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Models/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Models — Agent Charter - -## Mission -Define Notify DTOs and contracts per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Models — Agent Charter + +## Mission +Define Notify DTOs and contracts per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Queue/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Queue/AGENTS.md index ba755be3..d3476125 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Queue/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Queue/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Queue — Agent Charter - -## Mission -Provide event & delivery queues for Notify per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Queue — Agent Charter + +## Mission +Provide event & delivery queues for Notify per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/AGENTS.md b/src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/AGENTS.md index 22cb2910..120961bd 100644 --- a/src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/AGENTS.md +++ b/src/Notify/__Libraries/StellaOps.Notify.Storage.Mongo/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Notify.Storage.Mongo — Agent Charter - -## Mission -Implement Mongo persistence (rules, channels, deliveries, digests, locks, audit) per `docs/ARCHITECTURE_NOTIFY.md`. +# StellaOps.Notify.Storage.Mongo — Agent Charter + +## Mission +Implement Mongo persistence (rules, channels, deliveries, digests, locks, audit) per `docs/modules/notify/ARCHITECTURE.md`. diff --git a/src/Notify/__Tests/StellaOps.Notify.Models.Tests/StellaOps.Notify.Models.Tests.csproj b/src/Notify/__Tests/StellaOps.Notify.Models.Tests/StellaOps.Notify.Models.Tests.csproj index a045323d..3bc1db16 100644 --- a/src/Notify/__Tests/StellaOps.Notify.Models.Tests/StellaOps.Notify.Models.Tests.csproj +++ b/src/Notify/__Tests/StellaOps.Notify.Models.Tests/StellaOps.Notify.Models.Tests.csproj @@ -18,7 +18,7 @@ Always - + Always diff --git a/src/Notify/__Tests/StellaOps.Notify.Storage.Mongo.Tests/StellaOps.Notify.Storage.Mongo.Tests.csproj b/src/Notify/__Tests/StellaOps.Notify.Storage.Mongo.Tests/StellaOps.Notify.Storage.Mongo.Tests.csproj index 26c85a17..2aa5e9de 100644 --- a/src/Notify/__Tests/StellaOps.Notify.Storage.Mongo.Tests/StellaOps.Notify.Storage.Mongo.Tests.csproj +++ b/src/Notify/__Tests/StellaOps.Notify.Storage.Mongo.Tests/StellaOps.Notify.Storage.Mongo.Tests.csproj @@ -22,8 +22,8 @@ - + Always - \ No newline at end of file + diff --git a/src/Notify/__Tests/StellaOps.Notify.WebService.Tests/StellaOps.Notify.WebService.Tests.csproj b/src/Notify/__Tests/StellaOps.Notify.WebService.Tests/StellaOps.Notify.WebService.Tests.csproj index 18e0788d..998562da 100644 --- a/src/Notify/__Tests/StellaOps.Notify.WebService.Tests/StellaOps.Notify.WebService.Tests.csproj +++ b/src/Notify/__Tests/StellaOps.Notify.WebService.Tests/StellaOps.Notify.WebService.Tests.csproj @@ -12,8 +12,8 @@ - + Always - \ No newline at end of file + diff --git a/src/Policy/__Libraries/StellaOps.Policy/AGENTS.md b/src/Policy/__Libraries/StellaOps.Policy/AGENTS.md index 14a6c360..973b3d8d 100644 --- a/src/Policy/__Libraries/StellaOps.Policy/AGENTS.md +++ b/src/Policy/__Libraries/StellaOps.Policy/AGENTS.md @@ -1,12 +1,12 @@ -# StellaOps.Policy — Agent Charter - -## Mission -Deliver the policy engine outlined in `docs/ARCHITECTURE_SCANNER.md` and related prose: -- Define YAML schema (ignore rules, VEX inclusion/exclusion, vendor precedence, license gates). -- Provide policy snapshot storage with revision digests and diagnostics. -- Offer preview APIs to compare policy impacts on existing reports. - -## Expectations -- Coordinate with Scanner.WebService, Feedser, Vexer, UI, Notify. -- Maintain deterministic serialization and unit tests for precedence rules. -- Update `TASKS.md` and broadcast contract changes. +# StellaOps.Policy — Agent Charter + +## Mission +Deliver the policy engine outlined in `docs/modules/scanner/ARCHITECTURE.md` and related prose: +- Define YAML schema (ignore rules, VEX inclusion/exclusion, vendor precedence, license gates). +- Provide policy snapshot storage with revision digests and diagnostics. +- Offer preview APIs to compare policy impacts on existing reports. + +## Expectations +- Coordinate with Scanner.WebService, Feedser, Vexer, UI, Notify. +- Maintain deterministic serialization and unit tests for precedence rules. +- Update `TASKS.md` and broadcast contract changes. diff --git a/src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/AGENTS.md b/src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/AGENTS.md index 7b119d2c..220ee026 100644 --- a/src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/AGENTS.md +++ b/src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/AGENTS.md @@ -1,12 +1,12 @@ -# StellaOps.Scanner.Sbomer.BuildXPlugin — Agent Charter - -## Mission -Implement the build-time SBOM generator described in `docs/ARCHITECTURE_SCANNER.md` and new buildx dossier requirements: -- Provide a deterministic BuildKit/Buildx generator that produces layer SBOM fragments and uploads them to local CAS. -- Emit OCI annotations (+provenance) compatible with Scanner.Emit and Attestor hand-offs. -- Respect restart-time plug-in policy (`plugins/scanner/buildx/` manifests) and keep CI overhead ≤300 ms per layer. - -## Expectations -- Read architecture + upcoming Buildx addendum before coding. -- Ensure graceful fallback to post-build scan when generator unavailable. -- Provide integration tests with mock BuildKit, and update `TASKS.md` as states change. +# StellaOps.Scanner.Sbomer.BuildXPlugin — Agent Charter + +## Mission +Implement the build-time SBOM generator described in `docs/modules/scanner/ARCHITECTURE.md` and new buildx dossier requirements: +- Provide a deterministic BuildKit/Buildx generator that produces layer SBOM fragments and uploads them to local CAS. +- Emit OCI annotations (+provenance) compatible with Scanner.Emit and Attestor hand-offs. +- Respect restart-time plug-in policy (`plugins/scanner/buildx/` manifests) and keep CI overhead ≤300 ms per layer. + +## Expectations +- Read architecture + upcoming Buildx addendum before coding. +- Ensure graceful fallback to post-build scan when generator unavailable. +- Provide integration tests with mock BuildKit, and update `TASKS.md` as states change. diff --git a/src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md b/src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md index a4a90224..d004ae29 100644 --- a/src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md +++ b/src/Scanner/__Libraries/StellaOps.Scanner.Core/TASKS.md @@ -1,7 +1,7 @@ -# Scanner Core Task Board - -| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | -|----|--------|----------|------------|-------------|---------------| -| SCANNER-CORE-09-501 | DONE (2025-10-19) | Scanner Core Guild | — | Define shared DTOs (ScanJob, ProgressEvent), error taxonomy, and deterministic ID/timestamp helpers aligning with `ARCHITECTURE_SCANNER.md` §3–§4.
2025-10-19: Added golden fixtures + `ScannerCoreContractsTests` to lock canonical JSON.
2025-10-19: Published canonical JSON snippet + acceptance notes in `docs/scanner-core-contracts.md`. | DTOs serialize deterministically, helpers produce reproducible IDs/timestamps, tests cover round-trips and hash derivation. | -| SCANNER-CORE-09-502 | DONE (2025-10-19) | Scanner Core Guild | SCANNER-CORE-09-501 | Observability helpers (correlation IDs, logging scopes, metric namespacing, deterministic hashes) consumed by WebService/Worker.
2025-10-19: Verified progress scope serialisation via new fixtures/tests.
2025-10-19: Added `ScannerLogExtensionsPerformanceTests` to enforce ≤ 5 µs scope overhead + documented micro-bench results. | Logging/metrics helpers allocate minimally, correlation IDs stable, ActivitySource emitted; tests assert determinism. | -| SCANNER-CORE-09-503 | DONE (2025-10-18) | Scanner Core Guild | SCANNER-CORE-09-501, SCANNER-CORE-09-502 | Security utilities: Authority client factory, OpTok caching, DPoP verifier, restart-time plug-in guardrails for scanner components. | Authority helpers cache tokens, DPoP validator rejects invalid proofs, plug-in guard prevents runtime additions; tests cover happy/error paths. | +# Scanner Core Task Board + +| ID | Status | Owner(s) | Depends on | Description | Exit Criteria | +|----|--------|----------|------------|-------------|---------------| +| SCANNER-CORE-09-501 | DONE (2025-10-19) | Scanner Core Guild | — | Define shared DTOs (ScanJob, ProgressEvent), error taxonomy, and deterministic ID/timestamp helpers aligning with `modules/scanner/ARCHITECTURE.md` §3–§4.
2025-10-19: Added golden fixtures + `ScannerCoreContractsTests` to lock canonical JSON.
2025-10-19: Published canonical JSON snippet + acceptance notes in `docs/scanner-core-contracts.md`. | DTOs serialize deterministically, helpers produce reproducible IDs/timestamps, tests cover round-trips and hash derivation. | +| SCANNER-CORE-09-502 | DONE (2025-10-19) | Scanner Core Guild | SCANNER-CORE-09-501 | Observability helpers (correlation IDs, logging scopes, metric namespacing, deterministic hashes) consumed by WebService/Worker.
2025-10-19: Verified progress scope serialisation via new fixtures/tests.
2025-10-19: Added `ScannerLogExtensionsPerformanceTests` to enforce ≤ 5 µs scope overhead + documented micro-bench results. | Logging/metrics helpers allocate minimally, correlation IDs stable, ActivitySource emitted; tests assert determinism. | +| SCANNER-CORE-09-503 | DONE (2025-10-18) | Scanner Core Guild | SCANNER-CORE-09-501, SCANNER-CORE-09-502 | Security utilities: Authority client factory, OpTok caching, DPoP verifier, restart-time plug-in guardrails for scanner components. | Authority helpers cache tokens, DPoP validator rejects invalid proofs, plug-in guard prevents runtime additions; tests cover happy/error paths. | diff --git a/src/Scanner/__Libraries/StellaOps.Scanner.Queue/AGENTS.md b/src/Scanner/__Libraries/StellaOps.Scanner.Queue/AGENTS.md index b518ef76..cdbd6a25 100644 --- a/src/Scanner/__Libraries/StellaOps.Scanner.Queue/AGENTS.md +++ b/src/Scanner/__Libraries/StellaOps.Scanner.Queue/AGENTS.md @@ -1,15 +1,15 @@ -# StellaOps.Scanner.Queue — Agent Charter - -## Mission -Deliver the scanner job queue backbone defined in `docs/ARCHITECTURE_SCANNER.md`, providing deterministic, offline-friendly leasing semantics for WebService producers and Worker consumers. - -## Responsibilities -- Define queue abstractions with idempotent enqueue tokens, acknowledgement, lease renewal, and claim support. -- Ship first-party adapters for Redis Streams and NATS JetStream, respecting offline deployments and allow-listed hosts. -- Surface health probes, structured diagnostics, and metrics needed by Scanner WebService/Worker. -- Document operational expectations and configuration binding hooks. - -## Interfaces & Dependencies -- Consumes shared configuration primitives from `StellaOps.Configuration`. -- Exposes dependency injection extensions for `StellaOps.DependencyInjection`. -- Targets `net10.0` (preview) and aligns with scanner DTOs once `StellaOps.Scanner.Core` lands. +# StellaOps.Scanner.Queue — Agent Charter + +## Mission +Deliver the scanner job queue backbone defined in `docs/modules/scanner/ARCHITECTURE.md`, providing deterministic, offline-friendly leasing semantics for WebService producers and Worker consumers. + +## Responsibilities +- Define queue abstractions with idempotent enqueue tokens, acknowledgement, lease renewal, and claim support. +- Ship first-party adapters for Redis Streams and NATS JetStream, respecting offline deployments and allow-listed hosts. +- Surface health probes, structured diagnostics, and metrics needed by Scanner WebService/Worker. +- Document operational expectations and configuration binding hooks. + +## Interfaces & Dependencies +- Consumes shared configuration primitives from `StellaOps.Configuration`. +- Exposes dependency injection extensions for `StellaOps.DependencyInjection`. +- Targets `net10.0` (preview) and aligns with scanner DTOs once `StellaOps.Scanner.Core` lands. diff --git a/src/Scheduler/StellaOps.Scheduler.WebService/AGENTS.md b/src/Scheduler/StellaOps.Scheduler.WebService/AGENTS.md index 58a39ff2..18f067ff 100644 --- a/src/Scheduler/StellaOps.Scheduler.WebService/AGENTS.md +++ b/src/Scheduler/StellaOps.Scheduler.WebService/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Scheduler.WebService — Agent Charter - -## Mission -Implement Scheduler control plane per `docs/ARCHITECTURE_SCHEDULER.md`. +# StellaOps.Scheduler.WebService — Agent Charter + +## Mission +Implement Scheduler control plane per `docs/modules/scheduler/ARCHITECTURE.md`. diff --git a/src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/AGENTS.md b/src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/AGENTS.md index 9a52955a..8e43619c 100644 --- a/src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/AGENTS.md +++ b/src/Scheduler/__Libraries/StellaOps.Scheduler.ImpactIndex/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Scheduler.ImpactIndex — Agent Charter - -## Mission -Build the global impact index per `docs/ARCHITECTURE_SCHEDULER.md` (roaring bitmaps, selectors, snapshotting). +# StellaOps.Scheduler.ImpactIndex — Agent Charter + +## Mission +Build the global impact index per `docs/modules/scheduler/ARCHITECTURE.md` (roaring bitmaps, selectors, snapshotting). diff --git a/src/Scheduler/__Libraries/StellaOps.Scheduler.Models/AGENTS.md b/src/Scheduler/__Libraries/StellaOps.Scheduler.Models/AGENTS.md index 14ccf784..dbfefcb3 100644 --- a/src/Scheduler/__Libraries/StellaOps.Scheduler.Models/AGENTS.md +++ b/src/Scheduler/__Libraries/StellaOps.Scheduler.Models/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Scheduler.Models — Agent Charter - -## Mission -Define Scheduler DTOs (Schedule, Run, ImpactSet, Selector, DeltaSummary) per `docs/ARCHITECTURE_SCHEDULER.md`. +# StellaOps.Scheduler.Models — Agent Charter + +## Mission +Define Scheduler DTOs (Schedule, Run, ImpactSet, Selector, DeltaSummary) per `docs/modules/scheduler/ARCHITECTURE.md`. diff --git a/src/Scheduler/__Libraries/StellaOps.Scheduler.Queue/AGENTS.md b/src/Scheduler/__Libraries/StellaOps.Scheduler.Queue/AGENTS.md index 75b36a81..76161149 100644 --- a/src/Scheduler/__Libraries/StellaOps.Scheduler.Queue/AGENTS.md +++ b/src/Scheduler/__Libraries/StellaOps.Scheduler.Queue/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Scheduler.Queue — Agent Charter - -## Mission -Provide queue abstraction (Redis Streams / NATS JetStream) for planner inputs and runner segments per `docs/ARCHITECTURE_SCHEDULER.md`. +# StellaOps.Scheduler.Queue — Agent Charter + +## Mission +Provide queue abstraction (Redis Streams / NATS JetStream) for planner inputs and runner segments per `docs/modules/scheduler/ARCHITECTURE.md`. diff --git a/src/Scheduler/__Libraries/StellaOps.Scheduler.Storage.Mongo/AGENTS.md b/src/Scheduler/__Libraries/StellaOps.Scheduler.Storage.Mongo/AGENTS.md index a07b837e..fa008435 100644 --- a/src/Scheduler/__Libraries/StellaOps.Scheduler.Storage.Mongo/AGENTS.md +++ b/src/Scheduler/__Libraries/StellaOps.Scheduler.Storage.Mongo/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Scheduler.Storage.Mongo — Agent Charter - -## Mission -Implement Mongo persistence (schedules, runs, impact cursors, locks, audit) per `docs/ARCHITECTURE_SCHEDULER.md`. +# StellaOps.Scheduler.Storage.Mongo — Agent Charter + +## Mission +Implement Mongo persistence (schedules, runs, impact cursors, locks, audit) per `docs/modules/scheduler/ARCHITECTURE.md`. diff --git a/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/AGENTS.md b/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/AGENTS.md index 7c9a9c4b..c02a5198 100644 --- a/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/AGENTS.md +++ b/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/AGENTS.md @@ -1,4 +1,4 @@ -# StellaOps.Scheduler.Worker — Agent Charter - -## Mission -Implement Scheduler planners/runners per `docs/ARCHITECTURE_SCHEDULER.md`. +# StellaOps.Scheduler.Worker — Agent Charter + +## Mission +Implement Scheduler planners/runners per `docs/modules/scheduler/ARCHITECTURE.md`. diff --git a/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/docs/SCHED-WORKER-16-205-OBSERVABILITY.md b/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/docs/SCHED-WORKER-16-205-OBSERVABILITY.md index 3b948eb8..046e68a8 100644 --- a/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/docs/SCHED-WORKER-16-205-OBSERVABILITY.md +++ b/src/Scheduler/__Libraries/StellaOps.Scheduler.Worker/docs/SCHED-WORKER-16-205-OBSERVABILITY.md @@ -34,10 +34,10 @@ runner throughput, and backlog health. ## Dashboards & alerts -- **Grafana dashboard:** `docs/ops/scheduler-worker-grafana-dashboard.json` +- **Grafana dashboard:** `docs/modules/scheduler/operations/worker-grafana-dashboard.json` (import into Prometheus-backed Grafana). Panels mirror the metrics above with mode filters. -- **Prometheus rules:** `docs/ops/scheduler-worker-prometheus-rules.yaml` +- **Prometheus rules:** `docs/modules/scheduler/operations/worker-prometheus-rules.yaml` provides planner failure/latency, backlog, and stuck-run alerts. -- **Operations guide:** see `docs/ops/scheduler-worker-operations.md` for +- **Operations guide:** see `docs/modules/scheduler/operations/worker.md` for runbook steps, alert context, and dashboard wiring instructions. diff --git a/src/Tools/FixtureUpdater/FixtureUpdater.csproj b/src/Tools/FixtureUpdater/FixtureUpdater.csproj new file mode 100644 index 00000000..21ee8731 --- /dev/null +++ b/src/Tools/FixtureUpdater/FixtureUpdater.csproj @@ -0,0 +1,20 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + + + + + + + diff --git a/tools/FixtureUpdater/Program.cs b/src/Tools/FixtureUpdater/Program.cs similarity index 97% rename from tools/FixtureUpdater/Program.cs rename to src/Tools/FixtureUpdater/Program.cs index 86626780..27fb7cdf 100644 --- a/tools/FixtureUpdater/Program.cs +++ b/src/Tools/FixtureUpdater/Program.cs @@ -1,378 +1,378 @@ -using System.Linq; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using MongoDB.Bson; -using StellaOps.Concelier.Models; -using StellaOps.Concelier.Connector.Ghsa; -using StellaOps.Concelier.Connector.Common; -using StellaOps.Concelier.Connector.Ghsa.Internal; -using StellaOps.Concelier.Connector.Osv.Internal; -using StellaOps.Concelier.Connector.Osv; -using StellaOps.Concelier.Connector.Nvd; -using StellaOps.Concelier.Storage.Mongo.Documents; -using StellaOps.Concelier.Storage.Mongo.Dtos; - -var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) -{ - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, -}; - -var projectRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..")); - -var osvFixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Concelier.Connector.Osv.Tests", "Fixtures"); -var ghsaFixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Concelier.Connector.Ghsa.Tests", "Fixtures"); -var nvdFixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Concelier.Connector.Nvd.Tests", "Nvd", "Fixtures"); - -RewriteOsvFixtures(osvFixturesPath); -RewriteSnapshotFixtures(osvFixturesPath); -RewriteGhsaFixtures(osvFixturesPath); -RewriteCreditParityFixtures(ghsaFixturesPath, nvdFixturesPath); -return; - -void RewriteOsvFixtures(string fixturesPath) -{ - var rawPath = Path.Combine(fixturesPath, "osv-ghsa.raw-osv.json"); - if (!File.Exists(rawPath)) - { - Console.WriteLine($"[FixtureUpdater] OSV raw fixture missing: {rawPath}"); - return; - } - - using var document = JsonDocument.Parse(File.ReadAllText(rawPath)); - var advisories = new List(); - foreach (var element in document.RootElement.EnumerateArray()) - { - var dto = JsonSerializer.Deserialize(element.GetRawText(), serializerOptions); - if (dto is null) - { - continue; - } - - var ecosystem = dto.Affected?.FirstOrDefault()?.Package?.Ecosystem ?? "unknown"; - var uri = new Uri($"https://osv.dev/vulnerability/{dto.Id}"); - var documentRecord = new DocumentRecord( - Guid.NewGuid(), - OsvConnectorPlugin.SourceName, - uri.ToString(), - DateTimeOffset.UtcNow, - "fixture-sha", - DocumentStatuses.PendingMap, - "application/json", - null, - new Dictionary(StringComparer.Ordinal) - { - ["osv.ecosystem"] = ecosystem, - }, - null, - DateTimeOffset.UtcNow, - null, - null); - - var payload = BsonDocument.Parse(element.GetRawText()); - var dtoRecord = new DtoRecord( - Guid.NewGuid(), - documentRecord.Id, - OsvConnectorPlugin.SourceName, - "osv.v1", - payload, - DateTimeOffset.UtcNow); - - var advisory = OsvMapper.Map(dto, documentRecord, dtoRecord, ecosystem); - advisories.Add(advisory); - } - - advisories.Sort((left, right) => string.Compare(left.AdvisoryKey, right.AdvisoryKey, StringComparison.Ordinal)); - var snapshot = SnapshotSerializer.ToSnapshot(advisories); - File.WriteAllText(Path.Combine(fixturesPath, "osv-ghsa.osv.json"), snapshot); - Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, "osv-ghsa.osv.json")}"); -} - -void RewriteSnapshotFixtures(string fixturesPath) -{ - var baselinePublished = new DateTimeOffset(2025, 1, 5, 12, 0, 0, TimeSpan.Zero); - var baselineModified = new DateTimeOffset(2025, 1, 8, 6, 30, 0, TimeSpan.Zero); - var baselineFetched = new DateTimeOffset(2025, 1, 8, 7, 0, 0, TimeSpan.Zero); - - var cases = new (string Ecosystem, string Purl, string PackageName, string SnapshotFile)[] - { - ("npm", "pkg:npm/%40scope%2Fleft-pad", "@scope/left-pad", "osv-npm.snapshot.json"), - ("PyPI", "pkg:pypi/requests", "requests", "osv-pypi.snapshot.json"), - }; - - foreach (var (ecosystem, purl, packageName, snapshotFile) in cases) - { - var dto = new OsvVulnerabilityDto - { - Id = $"OSV-2025-{ecosystem}-0001", - Summary = $"{ecosystem} package vulnerability", - Details = $"Detailed description for {ecosystem} package {packageName}.", - Published = baselinePublished, - Modified = baselineModified, - Aliases = new[] { $"CVE-2025-11{ecosystem.Length}", $"GHSA-{ecosystem.Length}abc-{ecosystem.Length}def-{ecosystem.Length}ghi" }, - Related = new[] { $"OSV-RELATED-{ecosystem}-42" }, - References = new[] - { - new OsvReferenceDto { Url = $"https://example.com/{ecosystem}/advisory", Type = "ADVISORY" }, - new OsvReferenceDto { Url = $"https://example.com/{ecosystem}/fix", Type = "FIX" }, - }, - Severity = new[] - { - new OsvSeverityDto { Type = "CVSS_V3", Score = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" }, - }, - Affected = new[] - { - new OsvAffectedPackageDto - { - Package = new OsvPackageDto - { - Ecosystem = ecosystem, - Name = packageName, - Purl = purl, - }, - Ranges = new[] - { - new OsvRangeDto - { - Type = "SEMVER", - Events = new[] - { - new OsvEventDto { Introduced = "0" }, - new OsvEventDto { Fixed = "2.0.0" }, - }, - }, - }, - Versions = new[] { "1.0.0", "1.5.0" }, - EcosystemSpecific = JsonDocument.Parse("{\"severity\":\"high\"}").RootElement.Clone(), - }, - }, - DatabaseSpecific = JsonDocument.Parse("{\"source\":\"osv.dev\"}").RootElement.Clone(), - }; - - var document = new DocumentRecord( - Guid.NewGuid(), - OsvConnectorPlugin.SourceName, - $"https://osv.dev/vulnerability/{dto.Id}", - baselineFetched, - "fixture-sha", - DocumentStatuses.PendingParse, - "application/json", - null, - new Dictionary(StringComparer.Ordinal) { ["osv.ecosystem"] = ecosystem }, - null, - baselineModified, - null); - - var payload = BsonDocument.Parse(JsonSerializer.Serialize(dto, serializerOptions)); - var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, OsvConnectorPlugin.SourceName, "osv.v1", payload, baselineModified); - - var advisory = OsvMapper.Map(dto, document, dtoRecord, ecosystem); - var snapshot = SnapshotSerializer.ToSnapshot(advisory); - File.WriteAllText(Path.Combine(fixturesPath, snapshotFile), snapshot); - Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, snapshotFile)}"); - } -} - -void RewriteGhsaFixtures(string fixturesPath) -{ - var rawPath = Path.Combine(fixturesPath, "osv-ghsa.raw-ghsa.json"); - if (!File.Exists(rawPath)) - { - Console.WriteLine($"[FixtureUpdater] GHSA raw fixture missing: {rawPath}"); - return; - } - - JsonDocument document; - try - { - document = JsonDocument.Parse(File.ReadAllText(rawPath)); - } - catch (JsonException ex) - { - Console.WriteLine($"[FixtureUpdater] Failed to parse GHSA raw fixture '{rawPath}': {ex.Message}"); - return; - } - using (document) - { - var advisories = new List(); - foreach (var element in document.RootElement.EnumerateArray()) - { - GhsaRecordDto dto; - try - { - dto = GhsaRecordParser.Parse(Encoding.UTF8.GetBytes(element.GetRawText())); - } - catch (JsonException) - { - continue; - } - - var uri = new Uri($"https://github.com/advisories/{dto.GhsaId}"); - var documentRecord = new DocumentRecord( - Guid.NewGuid(), - GhsaConnectorPlugin.SourceName, - uri.ToString(), - DateTimeOffset.UtcNow, - "fixture-sha", - DocumentStatuses.PendingMap, - "application/json", - null, - new Dictionary(StringComparer.Ordinal), - null, - DateTimeOffset.UtcNow, - null, - null); - - var advisory = GhsaMapper.Map(dto, documentRecord, DateTimeOffset.UtcNow); - advisories.Add(advisory); - } - - advisories.Sort((left, right) => string.Compare(left.AdvisoryKey, right.AdvisoryKey, StringComparison.Ordinal)); - var snapshot = SnapshotSerializer.ToSnapshot(advisories); - File.WriteAllText(Path.Combine(fixturesPath, "osv-ghsa.ghsa.json"), snapshot); - Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, "osv-ghsa.ghsa.json")}"); - } -} - -void RewriteCreditParityFixtures(string ghsaFixturesPath, string nvdFixturesPath) -{ - Directory.CreateDirectory(ghsaFixturesPath); - Directory.CreateDirectory(nvdFixturesPath); - - var advisoryKeyGhsa = "GHSA-credit-parity"; - var advisoryKeyNvd = "CVE-2025-5555"; - var recordedAt = new DateTimeOffset(2025, 10, 10, 15, 0, 0, TimeSpan.Zero); - var published = new DateTimeOffset(2025, 10, 9, 18, 30, 0, TimeSpan.Zero); - var modified = new DateTimeOffset(2025, 10, 10, 12, 0, 0, TimeSpan.Zero); - - AdvisoryCredit[] CreateCredits(string source) => - [ - CreateCredit("Alice Researcher", "reporter", new[] { "mailto:alice.researcher@example.com" }, source), - CreateCredit("Bob Maintainer", "remediation_developer", new[] { "https://github.com/acme/bob-maintainer" }, source) - ]; - - AdvisoryCredit CreateCredit(string displayName, string role, IReadOnlyList contacts, string source) - { - var provenance = new AdvisoryProvenance( - source, - "credit", - $"{source}:{displayName.ToLowerInvariant().Replace(' ', '-')}", - recordedAt, - new[] { ProvenanceFieldMasks.Credits }); - - return new AdvisoryCredit(displayName, role, contacts, provenance); - } - - AdvisoryReference[] CreateReferences(string sourceName, params (string Url, string Kind)[] entries) - { - if (entries is null || entries.Length == 0) - { - return Array.Empty(); - } - - var references = new List(entries.Length); - foreach (var entry in entries) - { - var provenance = new AdvisoryProvenance( - sourceName, - "reference", - entry.Url, - recordedAt, - new[] { ProvenanceFieldMasks.References }); - - references.Add(new AdvisoryReference( - entry.Url, - entry.Kind, - sourceTag: null, - summary: null, - provenance)); - } - - return references.ToArray(); - } - - Advisory CreateAdvisory( - string sourceName, - string advisoryKey, - IEnumerable aliases, - AdvisoryCredit[] credits, - AdvisoryReference[] references, - string documentValue) - { - var documentProvenance = new AdvisoryProvenance( - sourceName, - "document", - documentValue, - recordedAt, - new[] { ProvenanceFieldMasks.Advisory }); - var mappingProvenance = new AdvisoryProvenance( - sourceName, - "mapping", - advisoryKey, - recordedAt, - new[] { ProvenanceFieldMasks.Advisory }); - - return new Advisory( - advisoryKey, - "Credit parity regression fixture", - "Credit parity regression fixture", - "en", - published, - modified, - "moderate", - exploitKnown: false, - aliases, - credits, - references, - Array.Empty(), - Array.Empty(), - new[] { documentProvenance, mappingProvenance }); - } - - var ghsa = CreateAdvisory( - "ghsa", - advisoryKeyGhsa, - new[] { advisoryKeyGhsa, advisoryKeyNvd }, - CreateCredits("ghsa"), - CreateReferences( - "ghsa", - ( $"https://github.com/advisories/{advisoryKeyGhsa}", "advisory"), - ( "https://example.com/ghsa/patch", "patch")), - $"security/advisories/{advisoryKeyGhsa}"); - - var osv = CreateAdvisory( - OsvConnectorPlugin.SourceName, - advisoryKeyGhsa, - new[] { advisoryKeyGhsa, advisoryKeyNvd }, - CreateCredits(OsvConnectorPlugin.SourceName), - CreateReferences( - OsvConnectorPlugin.SourceName, - ( $"https://github.com/advisories/{advisoryKeyGhsa}", "advisory"), - ( $"https://osv.dev/vulnerability/{advisoryKeyGhsa}", "advisory")), - $"https://osv.dev/vulnerability/{advisoryKeyGhsa}"); - - var nvd = CreateAdvisory( - NvdConnectorPlugin.SourceName, - advisoryKeyNvd, - new[] { advisoryKeyNvd, advisoryKeyGhsa }, - CreateCredits(NvdConnectorPlugin.SourceName), - CreateReferences( - NvdConnectorPlugin.SourceName, - ( $"https://services.nvd.nist.gov/vuln/detail/{advisoryKeyNvd}", "advisory"), - ( "https://example.com/nvd/reference", "report")), - $"https://services.nvd.nist.gov/vuln/detail/{advisoryKeyNvd}"); - - var ghsaSnapshot = SnapshotSerializer.ToSnapshot(ghsa); - var osvSnapshot = SnapshotSerializer.ToSnapshot(osv); - var nvdSnapshot = SnapshotSerializer.ToSnapshot(nvd); - - File.WriteAllText(Path.Combine(ghsaFixturesPath, "credit-parity.ghsa.json"), ghsaSnapshot); - File.WriteAllText(Path.Combine(ghsaFixturesPath, "credit-parity.osv.json"), osvSnapshot); - File.WriteAllText(Path.Combine(ghsaFixturesPath, "credit-parity.nvd.json"), nvdSnapshot); - - File.WriteAllText(Path.Combine(nvdFixturesPath, "credit-parity.ghsa.json"), ghsaSnapshot); - File.WriteAllText(Path.Combine(nvdFixturesPath, "credit-parity.osv.json"), osvSnapshot); - File.WriteAllText(Path.Combine(nvdFixturesPath, "credit-parity.nvd.json"), nvdSnapshot); - - Console.WriteLine($"[FixtureUpdater] Updated credit parity fixtures under {ghsaFixturesPath} and {nvdFixturesPath}"); -} +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using MongoDB.Bson; +using StellaOps.Concelier.Models; +using StellaOps.Concelier.Connector.Ghsa; +using StellaOps.Concelier.Connector.Common; +using StellaOps.Concelier.Connector.Ghsa.Internal; +using StellaOps.Concelier.Connector.Osv.Internal; +using StellaOps.Concelier.Connector.Osv; +using StellaOps.Concelier.Connector.Nvd; +using StellaOps.Concelier.Storage.Mongo.Documents; +using StellaOps.Concelier.Storage.Mongo.Dtos; + +var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) +{ + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, +}; + +var projectRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..")); + +var osvFixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Concelier.Connector.Osv.Tests", "Fixtures"); +var ghsaFixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Concelier.Connector.Ghsa.Tests", "Fixtures"); +var nvdFixturesPath = Path.Combine(projectRoot, "src", "StellaOps.Concelier.Connector.Nvd.Tests", "Nvd", "Fixtures"); + +RewriteOsvFixtures(osvFixturesPath); +RewriteSnapshotFixtures(osvFixturesPath); +RewriteGhsaFixtures(osvFixturesPath); +RewriteCreditParityFixtures(ghsaFixturesPath, nvdFixturesPath); +return; + +void RewriteOsvFixtures(string fixturesPath) +{ + var rawPath = Path.Combine(fixturesPath, "osv-ghsa.raw-osv.json"); + if (!File.Exists(rawPath)) + { + Console.WriteLine($"[FixtureUpdater] OSV raw fixture missing: {rawPath}"); + return; + } + + using var document = JsonDocument.Parse(File.ReadAllText(rawPath)); + var advisories = new List(); + foreach (var element in document.RootElement.EnumerateArray()) + { + var dto = JsonSerializer.Deserialize(element.GetRawText(), serializerOptions); + if (dto is null) + { + continue; + } + + var ecosystem = dto.Affected?.FirstOrDefault()?.Package?.Ecosystem ?? "unknown"; + var uri = new Uri($"https://osv.dev/vulnerability/{dto.Id}"); + var documentRecord = new DocumentRecord( + Guid.NewGuid(), + OsvConnectorPlugin.SourceName, + uri.ToString(), + DateTimeOffset.UtcNow, + "fixture-sha", + DocumentStatuses.PendingMap, + "application/json", + null, + new Dictionary(StringComparer.Ordinal) + { + ["osv.ecosystem"] = ecosystem, + }, + null, + DateTimeOffset.UtcNow, + null, + null); + + var payload = BsonDocument.Parse(element.GetRawText()); + var dtoRecord = new DtoRecord( + Guid.NewGuid(), + documentRecord.Id, + OsvConnectorPlugin.SourceName, + "osv.v1", + payload, + DateTimeOffset.UtcNow); + + var advisory = OsvMapper.Map(dto, documentRecord, dtoRecord, ecosystem); + advisories.Add(advisory); + } + + advisories.Sort((left, right) => string.Compare(left.AdvisoryKey, right.AdvisoryKey, StringComparison.Ordinal)); + var snapshot = SnapshotSerializer.ToSnapshot(advisories); + File.WriteAllText(Path.Combine(fixturesPath, "osv-ghsa.osv.json"), snapshot); + Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, "osv-ghsa.osv.json")}"); +} + +void RewriteSnapshotFixtures(string fixturesPath) +{ + var baselinePublished = new DateTimeOffset(2025, 1, 5, 12, 0, 0, TimeSpan.Zero); + var baselineModified = new DateTimeOffset(2025, 1, 8, 6, 30, 0, TimeSpan.Zero); + var baselineFetched = new DateTimeOffset(2025, 1, 8, 7, 0, 0, TimeSpan.Zero); + + var cases = new (string Ecosystem, string Purl, string PackageName, string SnapshotFile)[] + { + ("npm", "pkg:npm/%40scope%2Fleft-pad", "@scope/left-pad", "osv-npm.snapshot.json"), + ("PyPI", "pkg:pypi/requests", "requests", "osv-pypi.snapshot.json"), + }; + + foreach (var (ecosystem, purl, packageName, snapshotFile) in cases) + { + var dto = new OsvVulnerabilityDto + { + Id = $"OSV-2025-{ecosystem}-0001", + Summary = $"{ecosystem} package vulnerability", + Details = $"Detailed description for {ecosystem} package {packageName}.", + Published = baselinePublished, + Modified = baselineModified, + Aliases = new[] { $"CVE-2025-11{ecosystem.Length}", $"GHSA-{ecosystem.Length}abc-{ecosystem.Length}def-{ecosystem.Length}ghi" }, + Related = new[] { $"OSV-RELATED-{ecosystem}-42" }, + References = new[] + { + new OsvReferenceDto { Url = $"https://example.com/{ecosystem}/advisory", Type = "ADVISORY" }, + new OsvReferenceDto { Url = $"https://example.com/{ecosystem}/fix", Type = "FIX" }, + }, + Severity = new[] + { + new OsvSeverityDto { Type = "CVSS_V3", Score = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" }, + }, + Affected = new[] + { + new OsvAffectedPackageDto + { + Package = new OsvPackageDto + { + Ecosystem = ecosystem, + Name = packageName, + Purl = purl, + }, + Ranges = new[] + { + new OsvRangeDto + { + Type = "SEMVER", + Events = new[] + { + new OsvEventDto { Introduced = "0" }, + new OsvEventDto { Fixed = "2.0.0" }, + }, + }, + }, + Versions = new[] { "1.0.0", "1.5.0" }, + EcosystemSpecific = JsonDocument.Parse("{\"severity\":\"high\"}").RootElement.Clone(), + }, + }, + DatabaseSpecific = JsonDocument.Parse("{\"source\":\"osv.dev\"}").RootElement.Clone(), + }; + + var document = new DocumentRecord( + Guid.NewGuid(), + OsvConnectorPlugin.SourceName, + $"https://osv.dev/vulnerability/{dto.Id}", + baselineFetched, + "fixture-sha", + DocumentStatuses.PendingParse, + "application/json", + null, + new Dictionary(StringComparer.Ordinal) { ["osv.ecosystem"] = ecosystem }, + null, + baselineModified, + null); + + var payload = BsonDocument.Parse(JsonSerializer.Serialize(dto, serializerOptions)); + var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, OsvConnectorPlugin.SourceName, "osv.v1", payload, baselineModified); + + var advisory = OsvMapper.Map(dto, document, dtoRecord, ecosystem); + var snapshot = SnapshotSerializer.ToSnapshot(advisory); + File.WriteAllText(Path.Combine(fixturesPath, snapshotFile), snapshot); + Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, snapshotFile)}"); + } +} + +void RewriteGhsaFixtures(string fixturesPath) +{ + var rawPath = Path.Combine(fixturesPath, "osv-ghsa.raw-ghsa.json"); + if (!File.Exists(rawPath)) + { + Console.WriteLine($"[FixtureUpdater] GHSA raw fixture missing: {rawPath}"); + return; + } + + JsonDocument document; + try + { + document = JsonDocument.Parse(File.ReadAllText(rawPath)); + } + catch (JsonException ex) + { + Console.WriteLine($"[FixtureUpdater] Failed to parse GHSA raw fixture '{rawPath}': {ex.Message}"); + return; + } + using (document) + { + var advisories = new List(); + foreach (var element in document.RootElement.EnumerateArray()) + { + GhsaRecordDto dto; + try + { + dto = GhsaRecordParser.Parse(Encoding.UTF8.GetBytes(element.GetRawText())); + } + catch (JsonException) + { + continue; + } + + var uri = new Uri($"https://github.com/advisories/{dto.GhsaId}"); + var documentRecord = new DocumentRecord( + Guid.NewGuid(), + GhsaConnectorPlugin.SourceName, + uri.ToString(), + DateTimeOffset.UtcNow, + "fixture-sha", + DocumentStatuses.PendingMap, + "application/json", + null, + new Dictionary(StringComparer.Ordinal), + null, + DateTimeOffset.UtcNow, + null, + null); + + var advisory = GhsaMapper.Map(dto, documentRecord, DateTimeOffset.UtcNow); + advisories.Add(advisory); + } + + advisories.Sort((left, right) => string.Compare(left.AdvisoryKey, right.AdvisoryKey, StringComparison.Ordinal)); + var snapshot = SnapshotSerializer.ToSnapshot(advisories); + File.WriteAllText(Path.Combine(fixturesPath, "osv-ghsa.ghsa.json"), snapshot); + Console.WriteLine($"[FixtureUpdater] Updated {Path.Combine(fixturesPath, "osv-ghsa.ghsa.json")}"); + } +} + +void RewriteCreditParityFixtures(string ghsaFixturesPath, string nvdFixturesPath) +{ + Directory.CreateDirectory(ghsaFixturesPath); + Directory.CreateDirectory(nvdFixturesPath); + + var advisoryKeyGhsa = "GHSA-credit-parity"; + var advisoryKeyNvd = "CVE-2025-5555"; + var recordedAt = new DateTimeOffset(2025, 10, 10, 15, 0, 0, TimeSpan.Zero); + var published = new DateTimeOffset(2025, 10, 9, 18, 30, 0, TimeSpan.Zero); + var modified = new DateTimeOffset(2025, 10, 10, 12, 0, 0, TimeSpan.Zero); + + AdvisoryCredit[] CreateCredits(string source) => + [ + CreateCredit("Alice Researcher", "reporter", new[] { "mailto:alice.researcher@example.com" }, source), + CreateCredit("Bob Maintainer", "remediation_developer", new[] { "https://github.com/acme/bob-maintainer" }, source) + ]; + + AdvisoryCredit CreateCredit(string displayName, string role, IReadOnlyList contacts, string source) + { + var provenance = new AdvisoryProvenance( + source, + "credit", + $"{source}:{displayName.ToLowerInvariant().Replace(' ', '-')}", + recordedAt, + new[] { ProvenanceFieldMasks.Credits }); + + return new AdvisoryCredit(displayName, role, contacts, provenance); + } + + AdvisoryReference[] CreateReferences(string sourceName, params (string Url, string Kind)[] entries) + { + if (entries is null || entries.Length == 0) + { + return Array.Empty(); + } + + var references = new List(entries.Length); + foreach (var entry in entries) + { + var provenance = new AdvisoryProvenance( + sourceName, + "reference", + entry.Url, + recordedAt, + new[] { ProvenanceFieldMasks.References }); + + references.Add(new AdvisoryReference( + entry.Url, + entry.Kind, + sourceTag: null, + summary: null, + provenance)); + } + + return references.ToArray(); + } + + Advisory CreateAdvisory( + string sourceName, + string advisoryKey, + IEnumerable aliases, + AdvisoryCredit[] credits, + AdvisoryReference[] references, + string documentValue) + { + var documentProvenance = new AdvisoryProvenance( + sourceName, + "document", + documentValue, + recordedAt, + new[] { ProvenanceFieldMasks.Advisory }); + var mappingProvenance = new AdvisoryProvenance( + sourceName, + "mapping", + advisoryKey, + recordedAt, + new[] { ProvenanceFieldMasks.Advisory }); + + return new Advisory( + advisoryKey, + "Credit parity regression fixture", + "Credit parity regression fixture", + "en", + published, + modified, + "moderate", + exploitKnown: false, + aliases, + credits, + references, + Array.Empty(), + Array.Empty(), + new[] { documentProvenance, mappingProvenance }); + } + + var ghsa = CreateAdvisory( + "ghsa", + advisoryKeyGhsa, + new[] { advisoryKeyGhsa, advisoryKeyNvd }, + CreateCredits("ghsa"), + CreateReferences( + "ghsa", + ( $"https://github.com/advisories/{advisoryKeyGhsa}", "advisory"), + ( "https://example.com/ghsa/patch", "patch")), + $"security/advisories/{advisoryKeyGhsa}"); + + var osv = CreateAdvisory( + OsvConnectorPlugin.SourceName, + advisoryKeyGhsa, + new[] { advisoryKeyGhsa, advisoryKeyNvd }, + CreateCredits(OsvConnectorPlugin.SourceName), + CreateReferences( + OsvConnectorPlugin.SourceName, + ( $"https://github.com/advisories/{advisoryKeyGhsa}", "advisory"), + ( $"https://osv.dev/vulnerability/{advisoryKeyGhsa}", "advisory")), + $"https://osv.dev/vulnerability/{advisoryKeyGhsa}"); + + var nvd = CreateAdvisory( + NvdConnectorPlugin.SourceName, + advisoryKeyNvd, + new[] { advisoryKeyNvd, advisoryKeyGhsa }, + CreateCredits(NvdConnectorPlugin.SourceName), + CreateReferences( + NvdConnectorPlugin.SourceName, + ( $"https://services.nvd.nist.gov/vuln/detail/{advisoryKeyNvd}", "advisory"), + ( "https://example.com/nvd/reference", "report")), + $"https://services.nvd.nist.gov/vuln/detail/{advisoryKeyNvd}"); + + var ghsaSnapshot = SnapshotSerializer.ToSnapshot(ghsa); + var osvSnapshot = SnapshotSerializer.ToSnapshot(osv); + var nvdSnapshot = SnapshotSerializer.ToSnapshot(nvd); + + File.WriteAllText(Path.Combine(ghsaFixturesPath, "credit-parity.ghsa.json"), ghsaSnapshot); + File.WriteAllText(Path.Combine(ghsaFixturesPath, "credit-parity.osv.json"), osvSnapshot); + File.WriteAllText(Path.Combine(ghsaFixturesPath, "credit-parity.nvd.json"), nvdSnapshot); + + File.WriteAllText(Path.Combine(nvdFixturesPath, "credit-parity.ghsa.json"), ghsaSnapshot); + File.WriteAllText(Path.Combine(nvdFixturesPath, "credit-parity.osv.json"), osvSnapshot); + File.WriteAllText(Path.Combine(nvdFixturesPath, "credit-parity.nvd.json"), nvdSnapshot); + + Console.WriteLine($"[FixtureUpdater] Updated credit parity fixtures under {ghsaFixturesPath} and {nvdFixturesPath}"); +} diff --git a/tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj b/src/Tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj similarity index 97% rename from tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj rename to src/Tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj index a7490b33..5828535c 100644 --- a/tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj +++ b/src/Tools/LanguageAnalyzerSmoke/LanguageAnalyzerSmoke.csproj @@ -1,18 +1,18 @@ - - - - Exe - net10.0 - enable - enable - true - - - - - - - - - - + + + + Exe + net10.0 + enable + enable + true + + + + + + + + + + diff --git a/tools/LanguageAnalyzerSmoke/Program.cs b/src/Tools/LanguageAnalyzerSmoke/Program.cs similarity index 99% rename from tools/LanguageAnalyzerSmoke/Program.cs rename to src/Tools/LanguageAnalyzerSmoke/Program.cs index 907eb1d9..88cf380c 100644 --- a/tools/LanguageAnalyzerSmoke/Program.cs +++ b/src/Tools/LanguageAnalyzerSmoke/Program.cs @@ -78,7 +78,7 @@ internal sealed class SmokeOptions private static void PrintUsage() { Console.WriteLine("Language Analyzer Smoke Harness"); - Console.WriteLine("Usage: dotnet run --project tools/LanguageAnalyzerSmoke -- [options]"); + Console.WriteLine("Usage: dotnet run --project src/Tools/LanguageAnalyzerSmoke -- [options]"); Console.WriteLine(); Console.WriteLine("Options:"); Console.WriteLine(" -r, --repo-root Repository root (defaults to current working directory)"); diff --git a/tools/NotifySmokeCheck/NotifySmokeCheck.csproj b/src/Tools/NotifySmokeCheck/NotifySmokeCheck.csproj similarity index 97% rename from tools/NotifySmokeCheck/NotifySmokeCheck.csproj rename to src/Tools/NotifySmokeCheck/NotifySmokeCheck.csproj index b1e271b7..40dbf13e 100644 --- a/tools/NotifySmokeCheck/NotifySmokeCheck.csproj +++ b/src/Tools/NotifySmokeCheck/NotifySmokeCheck.csproj @@ -1,12 +1,12 @@ - - - Exe - net10.0 - enable - enable - true - - - - - + + + Exe + net10.0 + enable + enable + true + + + + + diff --git a/tools/NotifySmokeCheck/Program.cs b/src/Tools/NotifySmokeCheck/Program.cs similarity index 97% rename from tools/NotifySmokeCheck/Program.cs rename to src/Tools/NotifySmokeCheck/Program.cs index 1ed47417..6e04b797 100644 --- a/tools/NotifySmokeCheck/Program.cs +++ b/src/Tools/NotifySmokeCheck/Program.cs @@ -1,198 +1,198 @@ -using System.Globalization; -using System.Net.Http.Headers; -using System.Linq; -using System.Text.Json; -using StackExchange.Redis; - -static string RequireEnv(string name) -{ - var value = Environment.GetEnvironmentVariable(name); - if (string.IsNullOrWhiteSpace(value)) - { - throw new InvalidOperationException($"Environment variable '{name}' is required for Notify smoke validation."); - } - - return value; -} - -static string? GetField(StreamEntry entry, string fieldName) -{ - foreach (var pair in entry.Values) - { - if (string.Equals(pair.Name, fieldName, StringComparison.OrdinalIgnoreCase)) - { - return pair.Value.ToString(); - } - } - - return null; -} - -static void Ensure(bool condition, string message) -{ - if (!condition) - { - throw new InvalidOperationException(message); - } -} - -var redisDsn = RequireEnv("NOTIFY_SMOKE_REDIS_DSN"); -var redisStream = Environment.GetEnvironmentVariable("NOTIFY_SMOKE_STREAM"); -if (string.IsNullOrWhiteSpace(redisStream)) -{ - redisStream = "stella.events"; -} - -var expectedKindsEnv = RequireEnv("NOTIFY_SMOKE_EXPECT_KINDS"); - -var expectedKinds = expectedKindsEnv - .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) - .Select(kind => kind.ToLowerInvariant()) - .Distinct() - .ToArray(); -Ensure(expectedKinds.Length > 0, "Expected at least one event kind in NOTIFY_SMOKE_EXPECT_KINDS."); - -var lookbackMinutesEnv = RequireEnv("NOTIFY_SMOKE_LOOKBACK_MINUTES"); -if (!double.TryParse(lookbackMinutesEnv, NumberStyles.Any, CultureInfo.InvariantCulture, out var lookbackMinutes)) -{ - throw new InvalidOperationException("NOTIFY_SMOKE_LOOKBACK_MINUTES must be numeric."); -} -Ensure(lookbackMinutes > 0, "NOTIFY_SMOKE_LOOKBACK_MINUTES must be greater than zero."); - -var now = DateTimeOffset.UtcNow; -var sinceThreshold = now - TimeSpan.FromMinutes(Math.Max(1, lookbackMinutes)); - -Console.WriteLine($"ℹ️ Checking Redis stream '{redisStream}' for kinds [{string.Join(", ", expectedKinds)}] within the last {lookbackMinutes:F1} minutes."); - -var redisConfig = ConfigurationOptions.Parse(redisDsn); -redisConfig.AbortOnConnectFail = false; - -await using var redisConnection = await ConnectionMultiplexer.ConnectAsync(redisConfig); -var database = redisConnection.GetDatabase(); - -var streamEntries = await database.StreamRangeAsync(redisStream, "-", "+", count: 200); -if (streamEntries.Length > 1) -{ - Array.Reverse(streamEntries); -} -Ensure(streamEntries.Length > 0, $"Redis stream '{redisStream}' is empty."); - -var recentEntries = new List(); -foreach (var entry in streamEntries) -{ - var timestampText = GetField(entry, "ts"); - if (timestampText is null) - { - continue; - } - - if (!DateTimeOffset.TryParse(timestampText, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var entryTimestamp)) - { - continue; - } - - if (entryTimestamp >= sinceThreshold) - { - recentEntries.Add(entry); - } -} - -Ensure(recentEntries.Count > 0, $"No Redis events newer than {sinceThreshold:u} located in stream '{redisStream}'."); - -var missingKinds = new List(); -foreach (var kind in expectedKinds) -{ - var match = recentEntries.FirstOrDefault(entry => - { - var entryKind = GetField(entry, "kind")?.ToLowerInvariant(); - return entryKind == kind; - }); - - if (match.Equals(default(StreamEntry))) - { - missingKinds.Add(kind); - } -} - -Ensure(missingKinds.Count == 0, $"Missing expected Redis events for kinds: {string.Join(", ", missingKinds)}"); - -Console.WriteLine("✅ Redis event stream contains the expected scanner events."); - -var notifyBaseUrl = RequireEnv("NOTIFY_SMOKE_NOTIFY_BASEURL").TrimEnd('/'); -var notifyToken = RequireEnv("NOTIFY_SMOKE_NOTIFY_TOKEN"); -var notifyTenant = RequireEnv("NOTIFY_SMOKE_NOTIFY_TENANT"); -var notifyTenantHeader = Environment.GetEnvironmentVariable("NOTIFY_SMOKE_NOTIFY_TENANT_HEADER"); -if (string.IsNullOrWhiteSpace(notifyTenantHeader)) -{ - notifyTenantHeader = "X-StellaOps-Tenant"; -} - -var notifyTimeoutSeconds = 30; -var notifyTimeoutEnv = Environment.GetEnvironmentVariable("NOTIFY_SMOKE_NOTIFY_TIMEOUT_SECONDS"); -if (!string.IsNullOrWhiteSpace(notifyTimeoutEnv) && int.TryParse(notifyTimeoutEnv, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedTimeout)) -{ - notifyTimeoutSeconds = Math.Max(5, parsedTimeout); -} - -using var httpClient = new HttpClient -{ - Timeout = TimeSpan.FromSeconds(notifyTimeoutSeconds), -}; - -httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", notifyToken); -httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); -httpClient.DefaultRequestHeaders.Add(notifyTenantHeader, notifyTenant); - -var sinceQuery = Uri.EscapeDataString(sinceThreshold.ToString("O", CultureInfo.InvariantCulture)); -var deliveriesUrl = $"{notifyBaseUrl}/api/v1/deliveries?since={sinceQuery}&limit=200"; - -Console.WriteLine($"ℹ️ Querying Notify deliveries via {deliveriesUrl}."); - -using var response = await httpClient.GetAsync(deliveriesUrl); -if (!response.IsSuccessStatusCode) -{ - var body = await response.Content.ReadAsStringAsync(); - throw new InvalidOperationException($"Notify deliveries request failed with {(int)response.StatusCode} {response.ReasonPhrase}: {body}"); -} - -var json = await response.Content.ReadAsStringAsync(); -if (string.IsNullOrWhiteSpace(json)) -{ - throw new InvalidOperationException("Notify deliveries response body was empty."); -} - -using var document = JsonDocument.Parse(json); -var root = document.RootElement; - -IEnumerable EnumerateDeliveries(JsonElement element) -{ - return element.ValueKind switch - { - JsonValueKind.Array => element.EnumerateArray(), - JsonValueKind.Object when element.TryGetProperty("items", out var items) && items.ValueKind == JsonValueKind.Array => items.EnumerateArray(), - _ => throw new InvalidOperationException("Notify deliveries response was not an array or did not contain an 'items' collection.") - }; -} - -var deliveries = EnumerateDeliveries(root).ToArray(); -Ensure(deliveries.Length > 0, "Notify deliveries response did not return any records."); - -var missingDeliveryKinds = new List(); -foreach (var kind in expectedKinds) -{ - var found = deliveries.Any(delivery => - delivery.TryGetProperty("kind", out var kindProperty) && - kindProperty.GetString()?.Equals(kind, StringComparison.OrdinalIgnoreCase) == true && - delivery.TryGetProperty("status", out var statusProperty) && - !string.Equals(statusProperty.GetString(), "failed", StringComparison.OrdinalIgnoreCase)); - - if (!found) - { - missingDeliveryKinds.Add(kind); - } -} - -Ensure(missingDeliveryKinds.Count == 0, $"Notify deliveries missing successful records for kinds: {string.Join(", ", missingDeliveryKinds)}"); - -Console.WriteLine("✅ Notify deliveries include the expected scanner events."); -Console.WriteLine("🎉 Notify smoke validation completed successfully."); +using System.Globalization; +using System.Net.Http.Headers; +using System.Linq; +using System.Text.Json; +using StackExchange.Redis; + +static string RequireEnv(string name) +{ + var value = Environment.GetEnvironmentVariable(name); + if (string.IsNullOrWhiteSpace(value)) + { + throw new InvalidOperationException($"Environment variable '{name}' is required for Notify smoke validation."); + } + + return value; +} + +static string? GetField(StreamEntry entry, string fieldName) +{ + foreach (var pair in entry.Values) + { + if (string.Equals(pair.Name, fieldName, StringComparison.OrdinalIgnoreCase)) + { + return pair.Value.ToString(); + } + } + + return null; +} + +static void Ensure(bool condition, string message) +{ + if (!condition) + { + throw new InvalidOperationException(message); + } +} + +var redisDsn = RequireEnv("NOTIFY_SMOKE_REDIS_DSN"); +var redisStream = Environment.GetEnvironmentVariable("NOTIFY_SMOKE_STREAM"); +if (string.IsNullOrWhiteSpace(redisStream)) +{ + redisStream = "stella.events"; +} + +var expectedKindsEnv = RequireEnv("NOTIFY_SMOKE_EXPECT_KINDS"); + +var expectedKinds = expectedKindsEnv + .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(kind => kind.ToLowerInvariant()) + .Distinct() + .ToArray(); +Ensure(expectedKinds.Length > 0, "Expected at least one event kind in NOTIFY_SMOKE_EXPECT_KINDS."); + +var lookbackMinutesEnv = RequireEnv("NOTIFY_SMOKE_LOOKBACK_MINUTES"); +if (!double.TryParse(lookbackMinutesEnv, NumberStyles.Any, CultureInfo.InvariantCulture, out var lookbackMinutes)) +{ + throw new InvalidOperationException("NOTIFY_SMOKE_LOOKBACK_MINUTES must be numeric."); +} +Ensure(lookbackMinutes > 0, "NOTIFY_SMOKE_LOOKBACK_MINUTES must be greater than zero."); + +var now = DateTimeOffset.UtcNow; +var sinceThreshold = now - TimeSpan.FromMinutes(Math.Max(1, lookbackMinutes)); + +Console.WriteLine($"ℹ️ Checking Redis stream '{redisStream}' for kinds [{string.Join(", ", expectedKinds)}] within the last {lookbackMinutes:F1} minutes."); + +var redisConfig = ConfigurationOptions.Parse(redisDsn); +redisConfig.AbortOnConnectFail = false; + +await using var redisConnection = await ConnectionMultiplexer.ConnectAsync(redisConfig); +var database = redisConnection.GetDatabase(); + +var streamEntries = await database.StreamRangeAsync(redisStream, "-", "+", count: 200); +if (streamEntries.Length > 1) +{ + Array.Reverse(streamEntries); +} +Ensure(streamEntries.Length > 0, $"Redis stream '{redisStream}' is empty."); + +var recentEntries = new List(); +foreach (var entry in streamEntries) +{ + var timestampText = GetField(entry, "ts"); + if (timestampText is null) + { + continue; + } + + if (!DateTimeOffset.TryParse(timestampText, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var entryTimestamp)) + { + continue; + } + + if (entryTimestamp >= sinceThreshold) + { + recentEntries.Add(entry); + } +} + +Ensure(recentEntries.Count > 0, $"No Redis events newer than {sinceThreshold:u} located in stream '{redisStream}'."); + +var missingKinds = new List(); +foreach (var kind in expectedKinds) +{ + var match = recentEntries.FirstOrDefault(entry => + { + var entryKind = GetField(entry, "kind")?.ToLowerInvariant(); + return entryKind == kind; + }); + + if (match.Equals(default(StreamEntry))) + { + missingKinds.Add(kind); + } +} + +Ensure(missingKinds.Count == 0, $"Missing expected Redis events for kinds: {string.Join(", ", missingKinds)}"); + +Console.WriteLine("✅ Redis event stream contains the expected scanner events."); + +var notifyBaseUrl = RequireEnv("NOTIFY_SMOKE_NOTIFY_BASEURL").TrimEnd('/'); +var notifyToken = RequireEnv("NOTIFY_SMOKE_NOTIFY_TOKEN"); +var notifyTenant = RequireEnv("NOTIFY_SMOKE_NOTIFY_TENANT"); +var notifyTenantHeader = Environment.GetEnvironmentVariable("NOTIFY_SMOKE_NOTIFY_TENANT_HEADER"); +if (string.IsNullOrWhiteSpace(notifyTenantHeader)) +{ + notifyTenantHeader = "X-StellaOps-Tenant"; +} + +var notifyTimeoutSeconds = 30; +var notifyTimeoutEnv = Environment.GetEnvironmentVariable("NOTIFY_SMOKE_NOTIFY_TIMEOUT_SECONDS"); +if (!string.IsNullOrWhiteSpace(notifyTimeoutEnv) && int.TryParse(notifyTimeoutEnv, NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsedTimeout)) +{ + notifyTimeoutSeconds = Math.Max(5, parsedTimeout); +} + +using var httpClient = new HttpClient +{ + Timeout = TimeSpan.FromSeconds(notifyTimeoutSeconds), +}; + +httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", notifyToken); +httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); +httpClient.DefaultRequestHeaders.Add(notifyTenantHeader, notifyTenant); + +var sinceQuery = Uri.EscapeDataString(sinceThreshold.ToString("O", CultureInfo.InvariantCulture)); +var deliveriesUrl = $"{notifyBaseUrl}/api/v1/deliveries?since={sinceQuery}&limit=200"; + +Console.WriteLine($"ℹ️ Querying Notify deliveries via {deliveriesUrl}."); + +using var response = await httpClient.GetAsync(deliveriesUrl); +if (!response.IsSuccessStatusCode) +{ + var body = await response.Content.ReadAsStringAsync(); + throw new InvalidOperationException($"Notify deliveries request failed with {(int)response.StatusCode} {response.ReasonPhrase}: {body}"); +} + +var json = await response.Content.ReadAsStringAsync(); +if (string.IsNullOrWhiteSpace(json)) +{ + throw new InvalidOperationException("Notify deliveries response body was empty."); +} + +using var document = JsonDocument.Parse(json); +var root = document.RootElement; + +IEnumerable EnumerateDeliveries(JsonElement element) +{ + return element.ValueKind switch + { + JsonValueKind.Array => element.EnumerateArray(), + JsonValueKind.Object when element.TryGetProperty("items", out var items) && items.ValueKind == JsonValueKind.Array => items.EnumerateArray(), + _ => throw new InvalidOperationException("Notify deliveries response was not an array or did not contain an 'items' collection.") + }; +} + +var deliveries = EnumerateDeliveries(root).ToArray(); +Ensure(deliveries.Length > 0, "Notify deliveries response did not return any records."); + +var missingDeliveryKinds = new List(); +foreach (var kind in expectedKinds) +{ + var found = deliveries.Any(delivery => + delivery.TryGetProperty("kind", out var kindProperty) && + kindProperty.GetString()?.Equals(kind, StringComparison.OrdinalIgnoreCase) == true && + delivery.TryGetProperty("status", out var statusProperty) && + !string.Equals(statusProperty.GetString(), "failed", StringComparison.OrdinalIgnoreCase)); + + if (!found) + { + missingDeliveryKinds.Add(kind); + } +} + +Ensure(missingDeliveryKinds.Count == 0, $"Notify deliveries missing successful records for kinds: {string.Join(", ", missingDeliveryKinds)}"); + +Console.WriteLine("✅ Notify deliveries include the expected scanner events."); +Console.WriteLine("🎉 Notify smoke validation completed successfully."); diff --git a/tools/PolicyDslValidator/PolicyDslValidator.csproj b/src/Tools/PolicyDslValidator/PolicyDslValidator.csproj similarity index 96% rename from tools/PolicyDslValidator/PolicyDslValidator.csproj rename to src/Tools/PolicyDslValidator/PolicyDslValidator.csproj index 75115aee..edd23828 100644 --- a/tools/PolicyDslValidator/PolicyDslValidator.csproj +++ b/src/Tools/PolicyDslValidator/PolicyDslValidator.csproj @@ -1,14 +1,14 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/tools/PolicyDslValidator/Program.cs b/src/Tools/PolicyDslValidator/Program.cs similarity index 96% rename from tools/PolicyDslValidator/Program.cs rename to src/Tools/PolicyDslValidator/Program.cs index 931f38ad..a1420e6e 100644 --- a/tools/PolicyDslValidator/Program.cs +++ b/src/Tools/PolicyDslValidator/Program.cs @@ -1,56 +1,56 @@ -using StellaOps.Policy; - -if (args.Length == 0) -{ - Console.Error.WriteLine("Usage: policy-dsl-validator [--strict] [--json] [ ...]"); - Console.Error.WriteLine("Example: policy-dsl-validator --strict docs/examples/policies"); - return 64; // EX_USAGE -} - -var inputs = new List(); -var strict = false; -var outputJson = false; - -foreach (var arg in args) -{ - switch (arg) - { - case "--strict": - case "-s": - strict = true; - break; - - case "--json": - case "-j": - outputJson = true; - break; - - case "--help": - case "-h": - case "-?": - Console.WriteLine("Usage: policy-dsl-validator [--strict] [--json] [ ...]"); - Console.WriteLine("Example: policy-dsl-validator --strict docs/examples/policies"); - return 0; - - default: - inputs.Add(arg); - break; - } -} - -if (inputs.Count == 0) -{ - Console.Error.WriteLine("No input files or directories provided."); - return 64; // EX_USAGE -} - -var options = new PolicyValidationCliOptions -{ - Inputs = inputs, - Strict = strict, - OutputJson = outputJson, -}; - -var cli = new PolicyValidationCli(); -var exitCode = await cli.RunAsync(options, CancellationToken.None); -return exitCode; +using StellaOps.Policy; + +if (args.Length == 0) +{ + Console.Error.WriteLine("Usage: policy-dsl-validator [--strict] [--json] [ ...]"); + Console.Error.WriteLine("Example: policy-dsl-validator --strict docs/examples/policies"); + return 64; // EX_USAGE +} + +var inputs = new List(); +var strict = false; +var outputJson = false; + +foreach (var arg in args) +{ + switch (arg) + { + case "--strict": + case "-s": + strict = true; + break; + + case "--json": + case "-j": + outputJson = true; + break; + + case "--help": + case "-h": + case "-?": + Console.WriteLine("Usage: policy-dsl-validator [--strict] [--json] [ ...]"); + Console.WriteLine("Example: policy-dsl-validator --strict docs/examples/policies"); + return 0; + + default: + inputs.Add(arg); + break; + } +} + +if (inputs.Count == 0) +{ + Console.Error.WriteLine("No input files or directories provided."); + return 64; // EX_USAGE +} + +var options = new PolicyValidationCliOptions +{ + Inputs = inputs, + Strict = strict, + OutputJson = outputJson, +}; + +var cli = new PolicyValidationCli(); +var exitCode = await cli.RunAsync(options, CancellationToken.None); +return exitCode; diff --git a/tools/PolicySchemaExporter/PolicySchemaExporter.csproj b/src/Tools/PolicySchemaExporter/PolicySchemaExporter.csproj similarity index 81% rename from tools/PolicySchemaExporter/PolicySchemaExporter.csproj rename to src/Tools/PolicySchemaExporter/PolicySchemaExporter.csproj index 719c79b0..d89382a3 100644 --- a/tools/PolicySchemaExporter/PolicySchemaExporter.csproj +++ b/src/Tools/PolicySchemaExporter/PolicySchemaExporter.csproj @@ -1,21 +1,21 @@ - - - - Exe - net10.0 - enable - enable - true - - - - - - - - - - - - - + + + + Exe + net10.0 + enable + enable + true + + + + + + + + + + + + + diff --git a/tools/PolicySchemaExporter/Program.cs b/src/Tools/PolicySchemaExporter/Program.cs similarity index 94% rename from tools/PolicySchemaExporter/Program.cs rename to src/Tools/PolicySchemaExporter/Program.cs index bfd3467a..a63a3061 100644 --- a/tools/PolicySchemaExporter/Program.cs +++ b/src/Tools/PolicySchemaExporter/Program.cs @@ -1,48 +1,48 @@ -using System.Collections.Immutable; -using System.Text.Json; -using System.Text.Json.Serialization; -using NJsonSchema; -using NJsonSchema.Generation; -using NJsonSchema.Generation.SystemTextJson; -using Newtonsoft.Json; -using StellaOps.Scheduler.Models; - -var output = args.Length switch -{ - 0 => Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "docs", "schemas")), - 1 => Path.GetFullPath(args[0]), - _ => throw new ArgumentException("Usage: dotnet run --project tools/PolicySchemaExporter -- [outputDirectory]") -}; - -Directory.CreateDirectory(output); - -var generatorSettings = new SystemTextJsonSchemaGeneratorSettings -{ - SchemaType = SchemaType.JsonSchema, - DefaultReferenceTypeNullHandling = ReferenceTypeNullHandling.NotNull, - SerializerOptions = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase, - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - }, -}; - -var generator = new JsonSchemaGenerator(generatorSettings); - -var exports = ImmutableArray.Create( - (FileName: "policy-run-request.schema.json", Type: typeof(PolicyRunRequest)), - (FileName: "policy-run-status.schema.json", Type: typeof(PolicyRunStatus)), - (FileName: "policy-diff-summary.schema.json", Type: typeof(PolicyDiffSummary)), - (FileName: "policy-explain-trace.schema.json", Type: typeof(PolicyExplainTrace)) -); - -foreach (var export in exports) -{ - var schema = generator.Generate(export.Type); - schema.Title = export.Type.Name; - schema.AllowAdditionalProperties = false; - - var outputPath = Path.Combine(output, export.FileName); - await File.WriteAllTextAsync(outputPath, schema.ToJson(Formatting.Indented) + Environment.NewLine); - Console.WriteLine($"Wrote {outputPath}"); -} +using System.Collections.Immutable; +using System.Text.Json; +using System.Text.Json.Serialization; +using NJsonSchema; +using NJsonSchema.Generation; +using NJsonSchema.Generation.SystemTextJson; +using Newtonsoft.Json; +using StellaOps.Scheduler.Models; + +var output = args.Length switch +{ + 0 => Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "docs", "schemas")), + 1 => Path.GetFullPath(args[0]), + _ => throw new ArgumentException("Usage: dotnet run --project src/Tools/PolicySchemaExporter -- [outputDirectory]") +}; + +Directory.CreateDirectory(output); + +var generatorSettings = new SystemTextJsonSchemaGeneratorSettings +{ + SchemaType = SchemaType.JsonSchema, + DefaultReferenceTypeNullHandling = ReferenceTypeNullHandling.NotNull, + SerializerOptions = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + }, +}; + +var generator = new JsonSchemaGenerator(generatorSettings); + +var exports = ImmutableArray.Create( + (FileName: "policy-run-request.schema.json", Type: typeof(PolicyRunRequest)), + (FileName: "policy-run-status.schema.json", Type: typeof(PolicyRunStatus)), + (FileName: "policy-diff-summary.schema.json", Type: typeof(PolicyDiffSummary)), + (FileName: "policy-explain-trace.schema.json", Type: typeof(PolicyExplainTrace)) +); + +foreach (var export in exports) +{ + var schema = generator.Generate(export.Type); + schema.Title = export.Type.Name; + schema.AllowAdditionalProperties = false; + + var outputPath = Path.Combine(output, export.FileName); + await File.WriteAllTextAsync(outputPath, schema.ToJson(Formatting.Indented) + Environment.NewLine); + Console.WriteLine($"Wrote {outputPath}"); +} diff --git a/tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj b/src/Tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj similarity index 96% rename from tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj rename to src/Tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj index 034e2669..95b4d40b 100644 --- a/tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj +++ b/src/Tools/PolicySimulationSmoke/PolicySimulationSmoke.csproj @@ -1,14 +1,14 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/tools/PolicySimulationSmoke/Program.cs b/src/Tools/PolicySimulationSmoke/Program.cs similarity index 97% rename from tools/PolicySimulationSmoke/Program.cs rename to src/Tools/PolicySimulationSmoke/Program.cs index a6cb7440..8c537e63 100644 --- a/tools/PolicySimulationSmoke/Program.cs +++ b/src/Tools/PolicySimulationSmoke/Program.cs @@ -1,291 +1,291 @@ -using System.Collections.Immutable; -using System.Text.Json; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; -using StellaOps.Policy; - -var scenarioRoot = "samples/policy/simulations"; -string? outputDir = null; - -for (var i = 0; i < args.Length; i++) -{ - var arg = args[i]; - switch (arg) - { - case "--scenario-root": - case "-r": - if (i + 1 >= args.Length) - { - Console.Error.WriteLine("Missing value for --scenario-root."); - return 64; - } - scenarioRoot = args[++i]; - break; - case "--output": - case "-o": - if (i + 1 >= args.Length) - { - Console.Error.WriteLine("Missing value for --output."); - return 64; - } - outputDir = args[++i]; - break; - case "--help": - case "-h": - case "-?": - PrintUsage(); - return 0; - default: - Console.Error.WriteLine($"Unknown argument '{arg}'."); - PrintUsage(); - return 64; - } -} - -if (!Directory.Exists(scenarioRoot)) -{ - Console.Error.WriteLine($"Scenario root '{scenarioRoot}' does not exist."); - return 66; -} - -var scenarioFiles = Directory.GetFiles(scenarioRoot, "scenario.json", SearchOption.AllDirectories); -if (scenarioFiles.Length == 0) -{ - Console.Error.WriteLine($"No scenario.json files found under '{scenarioRoot}'."); - return 0; -} - -var loggerFactory = NullLoggerFactory.Instance; -var snapshotStore = new PolicySnapshotStore( - new NullPolicySnapshotRepository(), - new NullPolicyAuditRepository(), - TimeProvider.System, - loggerFactory.CreateLogger()); -var previewService = new PolicyPreviewService(snapshotStore, loggerFactory.CreateLogger()); - -var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) -{ - PropertyNameCaseInsensitive = true, - ReadCommentHandling = JsonCommentHandling.Skip, -}; - -var summary = new List(); -var success = true; - -foreach (var scenarioFile in scenarioFiles.OrderBy(static f => f, StringComparer.OrdinalIgnoreCase)) -{ - var scenarioText = await File.ReadAllTextAsync(scenarioFile); - var scenario = JsonSerializer.Deserialize(scenarioText, serializerOptions); - if (scenario is null) - { - Console.Error.WriteLine($"Failed to deserialize scenario '{scenarioFile}'."); - success = false; - continue; - } - - var repoRoot = Directory.GetCurrentDirectory(); - var policyPath = Path.Combine(repoRoot, scenario.PolicyPath); - if (!File.Exists(policyPath)) - { - Console.Error.WriteLine($"Policy file '{scenario.PolicyPath}' referenced by scenario '{scenario.Name}' does not exist."); - success = false; - continue; - } - - var policyContent = await File.ReadAllTextAsync(policyPath); - var policyFormat = PolicySchema.DetectFormat(policyPath); - var findings = scenario.Findings.Select(ToPolicyFinding).ToImmutableArray(); - var baseline = scenario.Baseline?.Select(ToPolicyVerdict).ToImmutableArray() ?? ImmutableArray.Empty; - - var request = new PolicyPreviewRequest( - ImageDigest: $"sha256:simulation-{scenario.Name}", - Findings: findings, - BaselineVerdicts: baseline, - SnapshotOverride: null, - ProposedPolicy: new PolicySnapshotContent( - Content: policyContent, - Format: policyFormat, - Actor: "ci", - Source: "ci/simulation-smoke", - Description: $"CI simulation for scenario '{scenario.Name}'")); - - var response = await previewService.PreviewAsync(request, CancellationToken.None); - var scenarioResult = EvaluateScenario(scenario, response); - summary.Add(scenarioResult); - - if (!scenarioResult.Success) - { - success = false; - } -} - -if (outputDir is not null) -{ - Directory.CreateDirectory(outputDir); - var summaryPath = Path.Combine(outputDir, "policy-simulation-summary.json"); - await File.WriteAllTextAsync(summaryPath, JsonSerializer.Serialize(summary, new JsonSerializerOptions { WriteIndented = true })); -} - -return success ? 0 : 1; - -static void PrintUsage() -{ - Console.WriteLine("Usage: policy-simulation-smoke [--scenario-root ] [--output ]"); - Console.WriteLine("Example: policy-simulation-smoke --scenario-root samples/policy/simulations --output artifacts/policy-simulations"); -} - -static PolicyFinding ToPolicyFinding(ScenarioFinding finding) -{ - var tags = finding.Tags is null ? ImmutableArray.Empty : ImmutableArray.CreateRange(finding.Tags); - var severity = Enum.Parse(finding.Severity, ignoreCase: true); - return new PolicyFinding( - finding.FindingId, - severity, - finding.Environment, - finding.Source, - finding.Vendor, - finding.License, - finding.Image, - finding.Repository, - finding.Package, - finding.Purl, - finding.Cve, - finding.Path, - finding.LayerDigest, - tags); -} - -static PolicyVerdict ToPolicyVerdict(ScenarioBaseline baseline) -{ - var status = Enum.Parse(baseline.Status, ignoreCase: true); - var inputs = baseline.Inputs?.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase) ?? ImmutableDictionary.Empty; - return new PolicyVerdict( - baseline.FindingId, - status, - RuleName: baseline.RuleName, - RuleAction: baseline.RuleAction, - Notes: baseline.Notes, - Score: baseline.Score, - ConfigVersion: baseline.ConfigVersion ?? PolicyScoringConfig.Default.Version, - Inputs: inputs, - QuietedBy: null, - Quiet: false, - UnknownConfidence: null, - ConfidenceBand: null, - UnknownAgeDays: null, - SourceTrust: null, - Reachability: null); -} - -static ScenarioResult EvaluateScenario(PolicySimulationScenario scenario, PolicyPreviewResponse response) -{ - var result = new ScenarioResult(scenario.Name); - if (!response.Success) - { - result.Failures.Add("Preview failed."); - return result with { Success = false, ChangedCount = response.ChangedCount }; - } - - var diffs = response.Diffs.ToDictionary(diff => diff.Projected.FindingId, StringComparer.OrdinalIgnoreCase); - foreach (var expected in scenario.ExpectedDiffs) - { - if (!diffs.TryGetValue(expected.FindingId, out var diff)) - { - result.Failures.Add($"Expected finding '{expected.FindingId}' missing from diff."); - continue; - } - - var projectedStatus = diff.Projected.Status.ToString(); - result.ActualStatuses[expected.FindingId] = projectedStatus; - if (!string.Equals(projectedStatus, expected.Status, StringComparison.OrdinalIgnoreCase)) - { - result.Failures.Add($"Finding '{expected.FindingId}' expected status '{expected.Status}' but was '{projectedStatus}'."); - } - } - - foreach (var diff in diffs.Values) - { - if (!result.ActualStatuses.ContainsKey(diff.Projected.FindingId)) - { - result.ActualStatuses[diff.Projected.FindingId] = diff.Projected.Status.ToString(); - } - } - - var success = result.Failures.Count == 0; - return result with - { - Success = success, - ChangedCount = response.ChangedCount - }; -} - -internal sealed record PolicySimulationScenario -{ - public string Name { get; init; } = "scenario"; - public string PolicyPath { get; init; } = string.Empty; - public List Findings { get; init; } = new(); - public List ExpectedDiffs { get; init; } = new(); - public List? Baseline { get; init; } -} - -internal sealed record ScenarioFinding -{ - public string FindingId { get; init; } = string.Empty; - public string Severity { get; init; } = "Low"; - public string? Environment { get; init; } - public string? Source { get; init; } - public string? Vendor { get; init; } - public string? License { get; init; } - public string? Image { get; init; } - public string? Repository { get; init; } - public string? Package { get; init; } - public string? Purl { get; init; } - public string? Cve { get; init; } - public string? Path { get; init; } - public string? LayerDigest { get; init; } - public string[]? Tags { get; init; } -} - -internal sealed record ScenarioExpectedDiff -{ - public string FindingId { get; init; } = string.Empty; - public string Status { get; init; } = "Pass"; -} - -internal sealed record ScenarioBaseline -{ - public string FindingId { get; init; } = string.Empty; - public string Status { get; init; } = "Pass"; - public string? RuleName { get; init; } - public string? RuleAction { get; init; } - public string? Notes { get; init; } - public double Score { get; init; } - public string? ConfigVersion { get; init; } - public Dictionary? Inputs { get; init; } -} - -internal sealed record ScenarioResult(string ScenarioName) -{ - public bool Success { get; init; } = true; - public int ChangedCount { get; init; } - public List Failures { get; } = new(); - public Dictionary ActualStatuses { get; } = new(StringComparer.OrdinalIgnoreCase); -} - -internal sealed class NullPolicySnapshotRepository : IPolicySnapshotRepository -{ - public Task AddAsync(PolicySnapshot snapshot, CancellationToken cancellationToken = default) => Task.CompletedTask; - - public Task GetLatestAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); - - public Task> ListAsync(int limit, CancellationToken cancellationToken = default) - => Task.FromResult>(Array.Empty()); -} - -internal sealed class NullPolicyAuditRepository : IPolicyAuditRepository -{ - public Task AddAsync(PolicyAuditEntry entry, CancellationToken cancellationToken = default) => Task.CompletedTask; - - public Task> ListAsync(int limit, CancellationToken cancellationToken = default) - => Task.FromResult>(Array.Empty()); -} +using System.Collections.Immutable; +using System.Text.Json; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using StellaOps.Policy; + +var scenarioRoot = "samples/policy/simulations"; +string? outputDir = null; + +for (var i = 0; i < args.Length; i++) +{ + var arg = args[i]; + switch (arg) + { + case "--scenario-root": + case "-r": + if (i + 1 >= args.Length) + { + Console.Error.WriteLine("Missing value for --scenario-root."); + return 64; + } + scenarioRoot = args[++i]; + break; + case "--output": + case "-o": + if (i + 1 >= args.Length) + { + Console.Error.WriteLine("Missing value for --output."); + return 64; + } + outputDir = args[++i]; + break; + case "--help": + case "-h": + case "-?": + PrintUsage(); + return 0; + default: + Console.Error.WriteLine($"Unknown argument '{arg}'."); + PrintUsage(); + return 64; + } +} + +if (!Directory.Exists(scenarioRoot)) +{ + Console.Error.WriteLine($"Scenario root '{scenarioRoot}' does not exist."); + return 66; +} + +var scenarioFiles = Directory.GetFiles(scenarioRoot, "scenario.json", SearchOption.AllDirectories); +if (scenarioFiles.Length == 0) +{ + Console.Error.WriteLine($"No scenario.json files found under '{scenarioRoot}'."); + return 0; +} + +var loggerFactory = NullLoggerFactory.Instance; +var snapshotStore = new PolicySnapshotStore( + new NullPolicySnapshotRepository(), + new NullPolicyAuditRepository(), + TimeProvider.System, + loggerFactory.CreateLogger()); +var previewService = new PolicyPreviewService(snapshotStore, loggerFactory.CreateLogger()); + +var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) +{ + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip, +}; + +var summary = new List(); +var success = true; + +foreach (var scenarioFile in scenarioFiles.OrderBy(static f => f, StringComparer.OrdinalIgnoreCase)) +{ + var scenarioText = await File.ReadAllTextAsync(scenarioFile); + var scenario = JsonSerializer.Deserialize(scenarioText, serializerOptions); + if (scenario is null) + { + Console.Error.WriteLine($"Failed to deserialize scenario '{scenarioFile}'."); + success = false; + continue; + } + + var repoRoot = Directory.GetCurrentDirectory(); + var policyPath = Path.Combine(repoRoot, scenario.PolicyPath); + if (!File.Exists(policyPath)) + { + Console.Error.WriteLine($"Policy file '{scenario.PolicyPath}' referenced by scenario '{scenario.Name}' does not exist."); + success = false; + continue; + } + + var policyContent = await File.ReadAllTextAsync(policyPath); + var policyFormat = PolicySchema.DetectFormat(policyPath); + var findings = scenario.Findings.Select(ToPolicyFinding).ToImmutableArray(); + var baseline = scenario.Baseline?.Select(ToPolicyVerdict).ToImmutableArray() ?? ImmutableArray.Empty; + + var request = new PolicyPreviewRequest( + ImageDigest: $"sha256:simulation-{scenario.Name}", + Findings: findings, + BaselineVerdicts: baseline, + SnapshotOverride: null, + ProposedPolicy: new PolicySnapshotContent( + Content: policyContent, + Format: policyFormat, + Actor: "ci", + Source: "ci/simulation-smoke", + Description: $"CI simulation for scenario '{scenario.Name}'")); + + var response = await previewService.PreviewAsync(request, CancellationToken.None); + var scenarioResult = EvaluateScenario(scenario, response); + summary.Add(scenarioResult); + + if (!scenarioResult.Success) + { + success = false; + } +} + +if (outputDir is not null) +{ + Directory.CreateDirectory(outputDir); + var summaryPath = Path.Combine(outputDir, "policy-simulation-summary.json"); + await File.WriteAllTextAsync(summaryPath, JsonSerializer.Serialize(summary, new JsonSerializerOptions { WriteIndented = true })); +} + +return success ? 0 : 1; + +static void PrintUsage() +{ + Console.WriteLine("Usage: policy-simulation-smoke [--scenario-root ] [--output ]"); + Console.WriteLine("Example: policy-simulation-smoke --scenario-root samples/policy/simulations --output artifacts/policy-simulations"); +} + +static PolicyFinding ToPolicyFinding(ScenarioFinding finding) +{ + var tags = finding.Tags is null ? ImmutableArray.Empty : ImmutableArray.CreateRange(finding.Tags); + var severity = Enum.Parse(finding.Severity, ignoreCase: true); + return new PolicyFinding( + finding.FindingId, + severity, + finding.Environment, + finding.Source, + finding.Vendor, + finding.License, + finding.Image, + finding.Repository, + finding.Package, + finding.Purl, + finding.Cve, + finding.Path, + finding.LayerDigest, + tags); +} + +static PolicyVerdict ToPolicyVerdict(ScenarioBaseline baseline) +{ + var status = Enum.Parse(baseline.Status, ignoreCase: true); + var inputs = baseline.Inputs?.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase) ?? ImmutableDictionary.Empty; + return new PolicyVerdict( + baseline.FindingId, + status, + RuleName: baseline.RuleName, + RuleAction: baseline.RuleAction, + Notes: baseline.Notes, + Score: baseline.Score, + ConfigVersion: baseline.ConfigVersion ?? PolicyScoringConfig.Default.Version, + Inputs: inputs, + QuietedBy: null, + Quiet: false, + UnknownConfidence: null, + ConfidenceBand: null, + UnknownAgeDays: null, + SourceTrust: null, + Reachability: null); +} + +static ScenarioResult EvaluateScenario(PolicySimulationScenario scenario, PolicyPreviewResponse response) +{ + var result = new ScenarioResult(scenario.Name); + if (!response.Success) + { + result.Failures.Add("Preview failed."); + return result with { Success = false, ChangedCount = response.ChangedCount }; + } + + var diffs = response.Diffs.ToDictionary(diff => diff.Projected.FindingId, StringComparer.OrdinalIgnoreCase); + foreach (var expected in scenario.ExpectedDiffs) + { + if (!diffs.TryGetValue(expected.FindingId, out var diff)) + { + result.Failures.Add($"Expected finding '{expected.FindingId}' missing from diff."); + continue; + } + + var projectedStatus = diff.Projected.Status.ToString(); + result.ActualStatuses[expected.FindingId] = projectedStatus; + if (!string.Equals(projectedStatus, expected.Status, StringComparison.OrdinalIgnoreCase)) + { + result.Failures.Add($"Finding '{expected.FindingId}' expected status '{expected.Status}' but was '{projectedStatus}'."); + } + } + + foreach (var diff in diffs.Values) + { + if (!result.ActualStatuses.ContainsKey(diff.Projected.FindingId)) + { + result.ActualStatuses[diff.Projected.FindingId] = diff.Projected.Status.ToString(); + } + } + + var success = result.Failures.Count == 0; + return result with + { + Success = success, + ChangedCount = response.ChangedCount + }; +} + +internal sealed record PolicySimulationScenario +{ + public string Name { get; init; } = "scenario"; + public string PolicyPath { get; init; } = string.Empty; + public List Findings { get; init; } = new(); + public List ExpectedDiffs { get; init; } = new(); + public List? Baseline { get; init; } +} + +internal sealed record ScenarioFinding +{ + public string FindingId { get; init; } = string.Empty; + public string Severity { get; init; } = "Low"; + public string? Environment { get; init; } + public string? Source { get; init; } + public string? Vendor { get; init; } + public string? License { get; init; } + public string? Image { get; init; } + public string? Repository { get; init; } + public string? Package { get; init; } + public string? Purl { get; init; } + public string? Cve { get; init; } + public string? Path { get; init; } + public string? LayerDigest { get; init; } + public string[]? Tags { get; init; } +} + +internal sealed record ScenarioExpectedDiff +{ + public string FindingId { get; init; } = string.Empty; + public string Status { get; init; } = "Pass"; +} + +internal sealed record ScenarioBaseline +{ + public string FindingId { get; init; } = string.Empty; + public string Status { get; init; } = "Pass"; + public string? RuleName { get; init; } + public string? RuleAction { get; init; } + public string? Notes { get; init; } + public double Score { get; init; } + public string? ConfigVersion { get; init; } + public Dictionary? Inputs { get; init; } +} + +internal sealed record ScenarioResult(string ScenarioName) +{ + public bool Success { get; init; } = true; + public int ChangedCount { get; init; } + public List Failures { get; } = new(); + public Dictionary ActualStatuses { get; } = new(StringComparer.OrdinalIgnoreCase); +} + +internal sealed class NullPolicySnapshotRepository : IPolicySnapshotRepository +{ + public Task AddAsync(PolicySnapshot snapshot, CancellationToken cancellationToken = default) => Task.CompletedTask; + + public Task GetLatestAsync(CancellationToken cancellationToken = default) => Task.FromResult(null); + + public Task> ListAsync(int limit, CancellationToken cancellationToken = default) + => Task.FromResult>(Array.Empty()); +} + +internal sealed class NullPolicyAuditRepository : IPolicyAuditRepository +{ + public Task AddAsync(PolicyAuditEntry entry, CancellationToken cancellationToken = default) => Task.CompletedTask; + + public Task> ListAsync(int limit, CancellationToken cancellationToken = default) + => Task.FromResult>(Array.Empty()); +} diff --git a/tools/RustFsMigrator/Program.cs b/src/Tools/RustFsMigrator/Program.cs similarity index 99% rename from tools/RustFsMigrator/Program.cs rename to src/Tools/RustFsMigrator/Program.cs index f9aa7b05..bae651e6 100644 --- a/tools/RustFsMigrator/Program.cs +++ b/src/Tools/RustFsMigrator/Program.cs @@ -270,7 +270,7 @@ internal sealed record MigrationOptions public static void PrintUsage() { - Console.WriteLine(@"Usage: dotnet run --project tools/RustFsMigrator -- \ + Console.WriteLine(@"Usage: dotnet run --project src/Tools/RustFsMigrator -- \ --s3-bucket \ [--s3-endpoint http://minio:9000] \ [--s3-region us-east-1] \ diff --git a/tools/RustFsMigrator/RustFsMigrator.csproj b/src/Tools/RustFsMigrator/RustFsMigrator.csproj similarity index 100% rename from tools/RustFsMigrator/RustFsMigrator.csproj rename to src/Tools/RustFsMigrator/RustFsMigrator.csproj diff --git a/tools/SourceStateSeeder/Program.cs b/src/Tools/SourceStateSeeder/Program.cs similarity index 98% rename from tools/SourceStateSeeder/Program.cs rename to src/Tools/SourceStateSeeder/Program.cs index 863655fd..a5fcccc8 100644 --- a/tools/SourceStateSeeder/Program.cs +++ b/src/Tools/SourceStateSeeder/Program.cs @@ -293,7 +293,7 @@ internal sealed record SeedOptions public static void PrintUsage() { - Console.WriteLine("Usage: dotnet run --project tools/SourceStateSeeder -- --connection-string --database --input [--source ]"); + Console.WriteLine("Usage: dotnet run --project src/Tools/SourceStateSeeder -- --connection-string --database --input [--source ]"); } private static string TakeValue(string[] args, ref int index, string arg) diff --git a/tools/SourceStateSeeder/SourceStateSeeder.csproj b/src/Tools/SourceStateSeeder/SourceStateSeeder.csproj similarity index 100% rename from tools/SourceStateSeeder/SourceStateSeeder.csproj rename to src/Tools/SourceStateSeeder/SourceStateSeeder.csproj diff --git a/tools/certbund_offline_snapshot.py b/src/Tools/certbund_offline_snapshot.py similarity index 99% rename from tools/certbund_offline_snapshot.py rename to src/Tools/certbund_offline_snapshot.py index ba33adb6..1d2342a3 100644 --- a/tools/certbund_offline_snapshot.py +++ b/src/Tools/certbund_offline_snapshot.py @@ -67,7 +67,7 @@ class CertBundClient: raise RuntimeError( "CERT-Bund XSRF token not available. Provide --xsrf-token or a cookie file " - "containing XSRF-TOKEN (see docs/ops/concelier-certbund-operations.md)." + "containing XSRF-TOKEN (see docs/modules/concelier/operations/connectors/certbund.md)." ) def fetch_search_pages( diff --git a/tools/openssl/linux-x64/libcrypto.so.1.1 b/src/Tools/openssl/linux-x64/libcrypto.so.1.1 similarity index 100% rename from tools/openssl/linux-x64/libcrypto.so.1.1 rename to src/Tools/openssl/linux-x64/libcrypto.so.1.1 diff --git a/tools/openssl/linux-x64/libssl.so.1.1 b/src/Tools/openssl/linux-x64/libssl.so.1.1 similarity index 100% rename from tools/openssl/linux-x64/libssl.so.1.1 rename to src/Tools/openssl/linux-x64/libssl.so.1.1 diff --git a/src/Zastava/StellaOps.Zastava.Webhook/IMPLEMENTATION_PLAN.md b/src/Zastava/StellaOps.Zastava.Webhook/IMPLEMENTATION_PLAN.md index 4045e0b3..88a15f5a 100644 --- a/src/Zastava/StellaOps.Zastava.Webhook/IMPLEMENTATION_PLAN.md +++ b/src/Zastava/StellaOps.Zastava.Webhook/IMPLEMENTATION_PLAN.md @@ -1,105 +1,105 @@ -# Zastava Webhook · Wave 0 Implementation Notes - -> Authored 2025-10-19 by Zastava Webhook Guild. - -## ZASTAVA-WEBHOOK-12-101 — Admission Controller Host (TLS bootstrap + Authority auth) - -**Objectives** -- Provide a deterministic, restart-safe .NET 10 host that exposes a Kubernetes ValidatingAdmissionWebhook endpoint. -- Load serving certificates at start-up only (per restart-time plug-in rule) and surface reload guidance via documentation rather than hot-reload. -- Authenticate outbound calls to Authority/Scanner using OpTok + DPoP as defined in `docs/ARCHITECTURE_ZASTAVA.md`. - -**Plan** -1. **Project scaffolding** - - Create `StellaOps.Zastava.Webhook` project with minimal API pipeline (`Program.cs`, `Startup` equivalent via extension methods). - - Reference shared helpers once `ZASTAVA-CORE-12-201/202` land; temporarily stub interfaces behind `IZastavaAdmissionRequest`/`IZastavaAdmissionResult`. -2. **TLS bootstrap** - - Support two certificate sources: - 1. Mounted secret path (`/var/run/secrets/zastava-webhook/tls.{crt,key}`) with optional CA bundle. - 2. CSR workflow: generate CSR + private key, submit to Kubernetes Certificates API when `admission.tls.autoApprove` enabled; persist signed cert/key to mounted emptyDir for reuse across replicas. - - Validate cert/key pair on boot; abort start-up if invalid to preserve deterministic behavior. - - Configure Kestrel for mutual TLS off (API Server already provides client auth) but enforce minimum TLS 1.3, strong cipher suite list, HTTP/2 disabled (K8s uses HTTP/1.1). +# Zastava Webhook · Wave 0 Implementation Notes + +> Authored 2025-10-19 by Zastava Webhook Guild. + +## ZASTAVA-WEBHOOK-12-101 — Admission Controller Host (TLS bootstrap + Authority auth) + +**Objectives** +- Provide a deterministic, restart-safe .NET 10 host that exposes a Kubernetes ValidatingAdmissionWebhook endpoint. +- Load serving certificates at start-up only (per restart-time plug-in rule) and surface reload guidance via documentation rather than hot-reload. +- Authenticate outbound calls to Authority/Scanner using OpTok + DPoP as defined in `docs/modules/zastava/ARCHITECTURE.md`. + +**Plan** +1. **Project scaffolding** + - Create `StellaOps.Zastava.Webhook` project with minimal API pipeline (`Program.cs`, `Startup` equivalent via extension methods). + - Reference shared helpers once `ZASTAVA-CORE-12-201/202` land; temporarily stub interfaces behind `IZastavaAdmissionRequest`/`IZastavaAdmissionResult`. +2. **TLS bootstrap** + - Support two certificate sources: + 1. Mounted secret path (`/var/run/secrets/zastava-webhook/tls.{crt,key}`) with optional CA bundle. + 2. CSR workflow: generate CSR + private key, submit to Kubernetes Certificates API when `admission.tls.autoApprove` enabled; persist signed cert/key to mounted emptyDir for reuse across replicas. + - Validate cert/key pair on boot; abort start-up if invalid to preserve deterministic behavior. + - Configure Kestrel for mutual TLS off (API Server already provides client auth) but enforce minimum TLS 1.3, strong cipher suite list, HTTP/2 disabled (K8s uses HTTP/1.1). 3. **Authority auth** - Bootstrap Authority client via shared runtime core (`AddZastavaRuntimeCore` + `IZastavaAuthorityTokenProvider`) so webhook reuses multitenant OpTok caching and guardrails. - - Implement DPoP proof generator bound to webhook host keypair (prefer Ed25519) with configurable rotation period (default 24h, triggered at restart). - - Add background health check verifying token freshness and surfacing metrics (`zastava.authority_token_renew_failures_total`). -4. **Hosting concerns** - - Configure structured logging with correlation id from AdmissionReview UID. - - Expose `/healthz` (reads cert expiry, Authority token status) and `/metrics` (Prometheus). - - Add readiness gate that requires initial TLS and Authority bootstrap to succeed. - -**Deliverables** -- Compilable host project with integration tests covering TLS load (mounted files + CSR mock) and Authority token acquisition. -- Documentation snippet for deploy charts describing secret/CSR wiring. - -**Open Questions** -- Need confirmation from Core guild on DTO naming (`AdmissionReviewEnvelope`, `AdmissionDecision`) to avoid rework. -- Determine whether CSR auto-approval is acceptable for air-gapped clusters without Kubernetes cert-manager; may require fallback manual cert import path. - -## ZASTAVA-WEBHOOK-12-102 — Backend policy query & digest resolution - -**Objectives** -- Resolve all images within AdmissionReview to immutable digests before policy evaluation. -- Call Scanner WebService `/api/v1/scanner/policy/runtime` with namespace/labels/images payload, enforce verdicts with deterministic error messaging. - -**Plan** -1. **Image resolution** - - Implement resolver service with pluggable strategies: - - Use existing digest if present. - - Resolve tags via registry HEAD (respecting `admission.resolveTags` flag); fallback to Observer-provided digest once core DTOs available. - - Cache per-registry auth to minimise latency; adhere to allow/deny lists from configuration. -2. **Scanner client** - - Define typed request/response models mirroring `docs/ARCHITECTURE_ZASTAVA.md` structure (`ttlSeconds`, `results[digest] -> { signed, hasSbom, policyVerdict, reasons, rekor }`). - - Implement retry policy (3 attempts, exponential backoff) and map HTTP errors to webhook fail-open/closed depending on namespace configuration. - - Instrument latency (`zastava.backend_latency_seconds`) and failure counts. -3. **Verdict enforcement** - - Evaluate per-image results: if any `policyVerdict != pass` (or `warn` when `enforceWarnings=false`), deny with aggregated reasons. - - Attach `ttlSeconds` to admission response annotations for auditing. - - Record structured logs with namespace, pod, image digest, decision, reasons, backend latency. -4. **Contract coordination** - - Schedule joint review with Scanner WebService guild once SCANNER-RUNTIME-12-302 schema stabilises; track in TASKS sub-items. - - Provide sample payload fixtures for CLI team (`CLI-RUNTIME-13-005`) to validate table output; ensure field names stay aligned. - -**Deliverables** -- Registry resolver unit tests (tag->digest) with deterministic fixtures. -- HTTP client integration tests using Scanner stub returning varied verdict combinations. -- Documentation update summarising contract and failure handling. - -**Open Questions** -- Confirm expected policy verdict enumeration (`pass|warn|fail|error`?) and textual reason codes. -- Need TTL behaviour: should webhook reduce TTL when backend returns > configured max? - -## ZASTAVA-WEBHOOK-12-103 — Caching, fail-open/closed toggles, metrics/logging - -**Objectives** -- Provide deterministic caching layer respecting backend TTL while ensuring eviction on policy mutation. -- Allow namespace-scoped fail-open behaviour with explicit metrics and alerts. -- Surface actionable metrics/logging aligned with Architecture doc. - -**Plan** -1. **Cache design** - - In-memory LRU keyed by image digest; value carries verdict payload + expiry timestamp. - - Support optional persistent seed (read-only) to prime hot digests for offline clusters (config: `admission.cache.seedPath`). - - On startup, load seed file and emit metric `zastava.cache_seed_entries_total`. - - Evict entries on TTL or when `policyRevision` annotation in AdmissionReview changes (requires hook from Core DTO). -2. **Fail-open/closed toggles** - - Configuration: global default + namespace overrides through `admission.failOpenNamespaces`, `admission.failClosedNamespaces`. - - Decision matrix: - - Backend success + verdict PASS → allow. - - Backend success + non-pass → deny unless namespace override says warn allowed. - - Backend failure → allow if namespace fail-open, deny otherwise; annotate response with `zastava.ops/fail-open=true`. - - Implement policy change event hook (future) to clear cache if observer signals revocation. -3. **Metrics & logging** - - Counters: `zastava.admission_requests_total{decision}`, `zastava.cache_hits_total{result=hit|miss}`, `zastava.fail_open_total`, `zastava.backend_failures_total{stage}`. - - Histograms: `zastava.admission_latency_seconds` (overall), `zastava.resolve_latency_seconds`. - - Logs: structured JSON with `decision`, `namespace`, `pod`, `imageDigest`, `reasons`, `cacheStatus`, `failMode`. - - Optionally emit OpenTelemetry span for admission path with attributes capturing backend latency + cache path. -4. **Testing & ops hooks** - - Unit tests for cache TTL, namespace override logic, fail-open metric increments. - - Integration test simulating backend outage ensuring fail-open/closed behaviour matches config. - - Document runbook snippet describing interpreting metrics and toggling namespaces. - -**Open Questions** -- Confirm whether cache entries should include `policyRevision` to detect backend policy updates; requires coordination with Policy guild. -- Need guidance on maximum cache size (default suggestions: 5k entries per replica?) to avoid memory blow-up. - + - Implement DPoP proof generator bound to webhook host keypair (prefer Ed25519) with configurable rotation period (default 24h, triggered at restart). + - Add background health check verifying token freshness and surfacing metrics (`zastava.authority_token_renew_failures_total`). +4. **Hosting concerns** + - Configure structured logging with correlation id from AdmissionReview UID. + - Expose `/healthz` (reads cert expiry, Authority token status) and `/metrics` (Prometheus). + - Add readiness gate that requires initial TLS and Authority bootstrap to succeed. + +**Deliverables** +- Compilable host project with integration tests covering TLS load (mounted files + CSR mock) and Authority token acquisition. +- Documentation snippet for deploy charts describing secret/CSR wiring. + +**Open Questions** +- Need confirmation from Core guild on DTO naming (`AdmissionReviewEnvelope`, `AdmissionDecision`) to avoid rework. +- Determine whether CSR auto-approval is acceptable for air-gapped clusters without Kubernetes cert-manager; may require fallback manual cert import path. + +## ZASTAVA-WEBHOOK-12-102 — Backend policy query & digest resolution + +**Objectives** +- Resolve all images within AdmissionReview to immutable digests before policy evaluation. +- Call Scanner WebService `/api/v1/scanner/policy/runtime` with namespace/labels/images payload, enforce verdicts with deterministic error messaging. + +**Plan** +1. **Image resolution** + - Implement resolver service with pluggable strategies: + - Use existing digest if present. + - Resolve tags via registry HEAD (respecting `admission.resolveTags` flag); fallback to Observer-provided digest once core DTOs available. + - Cache per-registry auth to minimise latency; adhere to allow/deny lists from configuration. +2. **Scanner client** + - Define typed request/response models mirroring `docs/modules/zastava/ARCHITECTURE.md` structure (`ttlSeconds`, `results[digest] -> { signed, hasSbom, policyVerdict, reasons, rekor }`). + - Implement retry policy (3 attempts, exponential backoff) and map HTTP errors to webhook fail-open/closed depending on namespace configuration. + - Instrument latency (`zastava.backend_latency_seconds`) and failure counts. +3. **Verdict enforcement** + - Evaluate per-image results: if any `policyVerdict != pass` (or `warn` when `enforceWarnings=false`), deny with aggregated reasons. + - Attach `ttlSeconds` to admission response annotations for auditing. + - Record structured logs with namespace, pod, image digest, decision, reasons, backend latency. +4. **Contract coordination** + - Schedule joint review with Scanner WebService guild once SCANNER-RUNTIME-12-302 schema stabilises; track in TASKS sub-items. + - Provide sample payload fixtures for CLI team (`CLI-RUNTIME-13-005`) to validate table output; ensure field names stay aligned. + +**Deliverables** +- Registry resolver unit tests (tag->digest) with deterministic fixtures. +- HTTP client integration tests using Scanner stub returning varied verdict combinations. +- Documentation update summarising contract and failure handling. + +**Open Questions** +- Confirm expected policy verdict enumeration (`pass|warn|fail|error`?) and textual reason codes. +- Need TTL behaviour: should webhook reduce TTL when backend returns > configured max? + +## ZASTAVA-WEBHOOK-12-103 — Caching, fail-open/closed toggles, metrics/logging + +**Objectives** +- Provide deterministic caching layer respecting backend TTL while ensuring eviction on policy mutation. +- Allow namespace-scoped fail-open behaviour with explicit metrics and alerts. +- Surface actionable metrics/logging aligned with Architecture doc. + +**Plan** +1. **Cache design** + - In-memory LRU keyed by image digest; value carries verdict payload + expiry timestamp. + - Support optional persistent seed (read-only) to prime hot digests for offline clusters (config: `admission.cache.seedPath`). + - On startup, load seed file and emit metric `zastava.cache_seed_entries_total`. + - Evict entries on TTL or when `policyRevision` annotation in AdmissionReview changes (requires hook from Core DTO). +2. **Fail-open/closed toggles** + - Configuration: global default + namespace overrides through `admission.failOpenNamespaces`, `admission.failClosedNamespaces`. + - Decision matrix: + - Backend success + verdict PASS → allow. + - Backend success + non-pass → deny unless namespace override says warn allowed. + - Backend failure → allow if namespace fail-open, deny otherwise; annotate response with `zastava.ops/fail-open=true`. + - Implement policy change event hook (future) to clear cache if observer signals revocation. +3. **Metrics & logging** + - Counters: `zastava.admission_requests_total{decision}`, `zastava.cache_hits_total{result=hit|miss}`, `zastava.fail_open_total`, `zastava.backend_failures_total{stage}`. + - Histograms: `zastava.admission_latency_seconds` (overall), `zastava.resolve_latency_seconds`. + - Logs: structured JSON with `decision`, `namespace`, `pod`, `imageDigest`, `reasons`, `cacheStatus`, `failMode`. + - Optionally emit OpenTelemetry span for admission path with attributes capturing backend latency + cache path. +4. **Testing & ops hooks** + - Unit tests for cache TTL, namespace override logic, fail-open metric increments. + - Integration test simulating backend outage ensuring fail-open/closed behaviour matches config. + - Document runbook snippet describing interpreting metrics and toggling namespaces. + +**Open Questions** +- Confirm whether cache entries should include `policyRevision` to detect backend policy updates; requires coordination with Policy guild. +- Need guidance on maximum cache size (default suggestions: 5k entries per replica?) to avoid memory blow-up. + diff --git a/tmp/docenv/pyvenv.cfg b/tmp/docenv/pyvenv.cfg deleted file mode 100644 index 2aff6b87..00000000 --- a/tmp/docenv/pyvenv.cfg +++ /dev/null @@ -1,5 +0,0 @@ -home = /usr/bin -include-system-site-packages = false -version = 3.12.3 -executable = /usr/bin/python3.12 -command = /usr/bin/python3 -m venv /mnt/e/dev/git.stella-ops.org/tmp/docenv diff --git a/tmp/reflect/Program.cs b/tmp/reflect/Program.cs deleted file mode 100644 index 9a08ba17..00000000 --- a/tmp/reflect/Program.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; - -var assembly = Assembly.Load("RoaringBitmap"); -foreach (var type in assembly.GetTypes().OrderBy(t => t.FullName)) -{ - Console.WriteLine(type.FullName); - foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly)) - { - Console.WriteLine($" {method.ReturnType.Name} {method.Name}({string.Join(", ", method.GetParameters().Select(p => p.ParameterType.Name + " " + p.Name))})"); - } -} diff --git a/tmp/reflect/reflect.csproj b/tmp/reflect/reflect.csproj deleted file mode 100644 index 55260214..00000000 --- a/tmp/reflect/reflect.csproj +++ /dev/null @@ -1,14 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - diff --git a/tools/FixtureUpdater/FixtureUpdater.csproj b/tools/FixtureUpdater/FixtureUpdater.csproj deleted file mode 100644 index 3a8ee640..00000000 --- a/tools/FixtureUpdater/FixtureUpdater.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - - Exe - net10.0 - enable - enable - - - - - - - - - - - - -