Add impact index fixture and filesystem artifact uploader
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
- Introduced a sample BOM index JSON file for impact index testing. - Created unit tests for the impact index fixture to ensure proper loading of sample images. - Implemented the FilesystemPackRunArtifactUploader class to handle artifact uploads to the local filesystem. - Added comprehensive tests for the FilesystemPackRunArtifactUploader, covering file copying, missing files, and expression outputs.
This commit is contained in:
@@ -23,13 +23,27 @@ This directory contains deterministic deployment bundles for the core Stella Ops
|
|||||||
`python ./ops/devops/telemetry/smoke_otel_collector.py` to verify the OTLP endpoints.
|
`python ./ops/devops/telemetry/smoke_otel_collector.py` to verify the OTLP endpoints.
|
||||||
5. Commit the change alongside any documentation updates (e.g. install guide cross-links).
|
5. Commit the change alongside any documentation updates (e.g. install guide cross-links).
|
||||||
|
|
||||||
Maintaining the digest linkage keeps offline/air-gapped installs reproducible and avoids tag drift between environments.
|
Maintaining the digest linkage keeps offline/air-gapped installs reproducible and avoids tag drift between environments.
|
||||||
|
|
||||||
### Additional tooling
|
### Surface.Env rollout warnings
|
||||||
|
|
||||||
- `deploy/tools/check-channel-alignment.py` – verifies that Helm/Compose profiles reference the exact images listed in a release manifest. Run it for each channel before promoting a release.
|
- Compose (`deploy/compose/env/*.env.example`) and Helm (`deploy/helm/stellaops/values-*.yaml`) now seed `SCANNER_SURFACE_*` variables so the worker and web service resolve cache roots, Surface.FS endpoints, and secrets providers through `StellaOps.Scanner.Surface.Env`.
|
||||||
- `ops/devops/telemetry/generate_dev_tls.sh` – produces local CA/server/client certificates for Compose-based collector testing.
|
- During rollout, watch for structured log messages (and readiness output) prefixed with `surface.env.`—for example, `surface.env.cache_root_missing`, `surface.env.endpoint_unreachable`, or `surface.env.secrets_provider_invalid`.
|
||||||
- `ops/devops/telemetry/smoke_otel_collector.py` – sends OTLP traffic and asserts the collector accepted traces, metrics, and logs.
|
- Treat these warnings as deployment blockers: update the endpoint/cache/secrets values or permissions before promoting the environment, otherwise workers will fail fast at startup.
|
||||||
|
- Air-gapped bundles default the secrets provider to `file` with `/etc/stellaops/secrets`; connected clusters default to `kubernetes`. Adjust the provider/root pair if your secrets manager differs.
|
||||||
|
|
||||||
|
### Mongo2Go OpenSSL prerequisites
|
||||||
|
|
||||||
|
- Linux runners that execute Mongo2Go-backed suites (Excititor, Scheduler, Graph, etc.) must expose OpenSSL 1.1 (`libcrypto.so.1.1`, `libssl.so.1.1`). The canonical copies live under `tests/native/openssl-1.1/linux-x64`.
|
||||||
|
- Export `LD_LIBRARY_PATH="$(git rev-parse --show-toplevel)/tests/native/openssl-1.1/linux-x64:${LD_LIBRARY_PATH:-}"` before invoking `dotnet test`. Example:\
|
||||||
|
`LD_LIBRARY_PATH="$(pwd)/tests/native/openssl-1.1/linux-x64" dotnet test src/Excititor/__Tests/StellaOps.Excititor.WebService.Tests/StellaOps.Excititor.WebService.Tests.csproj --nologo`.
|
||||||
|
- CI agents or Dockerfiles that host these tests should either mount the directory into the container or copy the two `.so` files into a directory that is already on the runtime library path.
|
||||||
|
|
||||||
|
### Additional tooling
|
||||||
|
|
||||||
|
- `deploy/tools/check-channel-alignment.py` – verifies that Helm/Compose profiles reference the exact images listed in a release manifest. Run it for each channel before promoting a release.
|
||||||
|
- `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.
|
- `ops/devops/telemetry/package_offline_bundle.py` – packages telemetry assets (config/Helm/Compose) into a signed tarball for air-gapped installs.
|
||||||
- `docs/modules/devops/runbooks/deployment-upgrade.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).
|
||||||
|
|
||||||
|
|||||||
4
deploy/compose/env/airgap.env.example
vendored
4
deploy/compose/env/airgap.env.example
vendored
@@ -27,6 +27,10 @@ SCANNER_EVENTS_DSN=
|
|||||||
SCANNER_EVENTS_STREAM=stella.events
|
SCANNER_EVENTS_STREAM=stella.events
|
||||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080/api/v1
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER=file
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT=/etc/stellaops/secrets
|
||||||
SCHEDULER_QUEUE_KIND=Nats
|
SCHEDULER_QUEUE_KIND=Nats
|
||||||
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
||||||
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
||||||
|
|||||||
5
deploy/compose/env/dev.env.example
vendored
5
deploy/compose/env/dev.env.example
vendored
@@ -26,6 +26,11 @@ SCANNER_EVENTS_DSN=
|
|||||||
SCANNER_EVENTS_STREAM=stella.events
|
SCANNER_EVENTS_STREAM=stella.events
|
||||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||||
|
# Surface.Env defaults keep worker/web service aligned with local RustFS and inline secrets.
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080/api/v1
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER=inline
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT=
|
||||||
SCHEDULER_QUEUE_KIND=Nats
|
SCHEDULER_QUEUE_KIND=Nats
|
||||||
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
||||||
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
||||||
|
|||||||
14
deploy/compose/env/mirror.env.example
vendored
14
deploy/compose/env/mirror.env.example
vendored
@@ -6,10 +6,16 @@ MONGO_INITDB_ROOT_PASSWORD=mirror-password
|
|||||||
MINIO_ROOT_USER=stellaops-mirror
|
MINIO_ROOT_USER=stellaops-mirror
|
||||||
MINIO_ROOT_PASSWORD=mirror-minio-secret
|
MINIO_ROOT_PASSWORD=mirror-minio-secret
|
||||||
RUSTFS_HTTP_PORT=8080
|
RUSTFS_HTTP_PORT=8080
|
||||||
|
|
||||||
# Mirror HTTP listeners
|
# Scanner surface integration
|
||||||
MIRROR_GATEWAY_HTTP_PORT=8080
|
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080/api/v1
|
||||||
MIRROR_GATEWAY_HTTPS_PORT=9443
|
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER=file
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT=/etc/stellaops/secrets
|
||||||
|
|
||||||
|
# Mirror HTTP listeners
|
||||||
|
MIRROR_GATEWAY_HTTP_PORT=8080
|
||||||
|
MIRROR_GATEWAY_HTTPS_PORT=9443
|
||||||
|
|
||||||
# Concelier mirror configuration
|
# Concelier mirror configuration
|
||||||
CONCELIER_MIRROR_LATEST_SEGMENT=latest
|
CONCELIER_MIRROR_LATEST_SEGMENT=latest
|
||||||
|
|||||||
8
deploy/compose/env/prod.env.example
vendored
8
deploy/compose/env/prod.env.example
vendored
@@ -26,9 +26,13 @@ SCANNER_EVENTS_ENABLED=true
|
|||||||
SCANNER_EVENTS_DRIVER=redis
|
SCANNER_EVENTS_DRIVER=redis
|
||||||
# Leave SCANNER_EVENTS_DSN empty to inherit the Redis queue DSN when SCANNER_QUEUE_BROKER uses redis://.
|
# Leave SCANNER_EVENTS_DSN empty to inherit the Redis queue DSN when SCANNER_QUEUE_BROKER uses redis://.
|
||||||
SCANNER_EVENTS_DSN=
|
SCANNER_EVENTS_DSN=
|
||||||
SCANNER_EVENTS_STREAM=stella.events
|
SCANNER_EVENTS_STREAM=stella.events
|
||||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT=https://surfacefs.prod.stella-ops.org/api/v1
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER=kubernetes
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT=stellaops/scanner
|
||||||
SCHEDULER_QUEUE_KIND=Nats
|
SCHEDULER_QUEUE_KIND=Nats
|
||||||
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
||||||
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
||||||
|
|||||||
4
deploy/compose/env/stage.env.example
vendored
4
deploy/compose/env/stage.env.example
vendored
@@ -26,6 +26,10 @@ SCANNER_EVENTS_DSN=
|
|||||||
SCANNER_EVENTS_STREAM=stella.events
|
SCANNER_EVENTS_STREAM=stella.events
|
||||||
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
SCANNER_EVENTS_PUBLISH_TIMEOUT_SECONDS=5
|
||||||
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
SCANNER_EVENTS_MAX_STREAM_LENGTH=10000
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT=http://rustfs:8080/api/v1
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT=/var/lib/stellaops/surface
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER=kubernetes
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT=stellaops/scanner
|
||||||
SCHEDULER_QUEUE_KIND=Nats
|
SCHEDULER_QUEUE_KIND=Nats
|
||||||
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
SCHEDULER_QUEUE_NATS_URL=nats://nats:4222
|
||||||
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
SCHEDULER_STORAGE_DATABASE=stellaops_scheduler
|
||||||
|
|||||||
@@ -1,102 +1,102 @@
|
|||||||
global:
|
global:
|
||||||
profile: airgap
|
profile: airgap
|
||||||
release:
|
release:
|
||||||
version: "2025.09.2-airgap"
|
version: "2025.09.2-airgap"
|
||||||
channel: airgap
|
channel: airgap
|
||||||
manifestSha256: "b787b833dddd73960c31338279daa0b0a0dce2ef32bd32ef1aaf953d66135f94"
|
manifestSha256: "b787b833dddd73960c31338279daa0b0a0dce2ef32bd32ef1aaf953d66135f94"
|
||||||
image:
|
image:
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
labels:
|
labels:
|
||||||
stellaops.io/channel: airgap
|
stellaops.io/channel: airgap
|
||||||
|
|
||||||
configMaps:
|
configMaps:
|
||||||
notify-config:
|
notify-config:
|
||||||
data:
|
data:
|
||||||
notify.yaml: |
|
notify.yaml: |
|
||||||
storage:
|
storage:
|
||||||
driver: mongo
|
driver: mongo
|
||||||
connectionString: "mongodb://notify-mongo.prod.svc.cluster.local:27017"
|
connectionString: "mongodb://notify-mongo.prod.svc.cluster.local:27017"
|
||||||
database: "stellaops_notify"
|
database: "stellaops_notify"
|
||||||
commandTimeoutSeconds: 60
|
commandTimeoutSeconds: 60
|
||||||
|
|
||||||
authority:
|
authority:
|
||||||
enabled: true
|
enabled: true
|
||||||
issuer: "https://authority.stella-ops.org"
|
issuer: "https://authority.stella-ops.org"
|
||||||
metadataAddress: "https://authority.stella-ops.org/.well-known/openid-configuration"
|
metadataAddress: "https://authority.stella-ops.org/.well-known/openid-configuration"
|
||||||
requireHttpsMetadata: true
|
requireHttpsMetadata: true
|
||||||
allowAnonymousFallback: false
|
allowAnonymousFallback: false
|
||||||
backchannelTimeoutSeconds: 30
|
backchannelTimeoutSeconds: 30
|
||||||
tokenClockSkewSeconds: 60
|
tokenClockSkewSeconds: 60
|
||||||
audiences:
|
audiences:
|
||||||
- notify
|
- notify
|
||||||
readScope: notify.read
|
readScope: notify.read
|
||||||
adminScope: notify.admin
|
adminScope: notify.admin
|
||||||
|
|
||||||
api:
|
api:
|
||||||
basePath: "/api/v1/notify"
|
basePath: "/api/v1/notify"
|
||||||
internalBasePath: "/internal/notify"
|
internalBasePath: "/internal/notify"
|
||||||
tenantHeader: "X-StellaOps-Tenant"
|
tenantHeader: "X-StellaOps-Tenant"
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
baseDirectory: "/var/opt/stellaops"
|
baseDirectory: "/var/opt/stellaops"
|
||||||
directory: "plugins/notify"
|
directory: "plugins/notify"
|
||||||
searchPatterns:
|
searchPatterns:
|
||||||
- "StellaOps.Notify.Connectors.*.dll"
|
- "StellaOps.Notify.Connectors.*.dll"
|
||||||
orderedPlugins:
|
orderedPlugins:
|
||||||
- StellaOps.Notify.Connectors.Slack
|
- StellaOps.Notify.Connectors.Slack
|
||||||
- StellaOps.Notify.Connectors.Teams
|
- StellaOps.Notify.Connectors.Teams
|
||||||
- StellaOps.Notify.Connectors.Email
|
- StellaOps.Notify.Connectors.Email
|
||||||
- StellaOps.Notify.Connectors.Webhook
|
- StellaOps.Notify.Connectors.Webhook
|
||||||
|
|
||||||
telemetry:
|
telemetry:
|
||||||
enableRequestLogging: true
|
enableRequestLogging: true
|
||||||
minimumLogLevel: Warning
|
minimumLogLevel: Warning
|
||||||
services:
|
services:
|
||||||
authority:
|
authority:
|
||||||
image: registry.stella-ops.org/stellaops/authority@sha256:5551a3269b7008cd5aceecf45df018c67459ed519557ccbe48b093b926a39bcc
|
image: registry.stella-ops.org/stellaops/authority@sha256:5551a3269b7008cd5aceecf45df018c67459ed519557ccbe48b093b926a39bcc
|
||||||
service:
|
service:
|
||||||
port: 8440
|
port: 8440
|
||||||
env:
|
env:
|
||||||
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
|
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
|
||||||
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
STELLAOPS_AUTHORITY__ALLOWANONYMOUSFALLBACK: "false"
|
STELLAOPS_AUTHORITY__ALLOWANONYMOUSFALLBACK: "false"
|
||||||
signer:
|
signer:
|
||||||
image: registry.stella-ops.org/stellaops/signer@sha256:ddbbd664a42846cea6b40fca6465bc679b30f72851158f300d01a8571c5478fc
|
image: registry.stella-ops.org/stellaops/signer@sha256:ddbbd664a42846cea6b40fca6465bc679b30f72851158f300d01a8571c5478fc
|
||||||
service:
|
service:
|
||||||
port: 8441
|
port: 8441
|
||||||
env:
|
env:
|
||||||
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
SIGNER__POE__INTROSPECTURL: "file:///offline/poe/introspect.json"
|
SIGNER__POE__INTROSPECTURL: "file:///offline/poe/introspect.json"
|
||||||
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
attestor:
|
attestor:
|
||||||
image: registry.stella-ops.org/stellaops/attestor@sha256:1ff0a3124d66d3a2702d8e421df40fbd98cc75cb605d95510598ebbae1433c50
|
image: registry.stella-ops.org/stellaops/attestor@sha256:1ff0a3124d66d3a2702d8e421df40fbd98cc75cb605d95510598ebbae1433c50
|
||||||
service:
|
service:
|
||||||
port: 8442
|
port: 8442
|
||||||
env:
|
env:
|
||||||
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
||||||
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
concelier:
|
concelier:
|
||||||
image: registry.stella-ops.org/stellaops/concelier@sha256:29e2e1a0972707e092cbd3d370701341f9fec2aa9316fb5d8100480f2a1c76b5
|
image: registry.stella-ops.org/stellaops/concelier@sha256:29e2e1a0972707e092cbd3d370701341f9fec2aa9316fb5d8100480f2a1c76b5
|
||||||
service:
|
service:
|
||||||
port: 8445
|
port: 8445
|
||||||
env:
|
env:
|
||||||
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
||||||
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-airgap"
|
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-airgap"
|
||||||
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "airgap-minio-secret"
|
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "airgap-minio-secret"
|
||||||
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
|
CONCELIER__AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
|
||||||
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "00:45:00"
|
CONCELIER__AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "00:45:00"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
mountPath: /var/lib/concelier/jobs
|
mountPath: /var/lib/concelier/jobs
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
claimName: stellaops-concelier-jobs
|
claimName: stellaops-concelier-jobs
|
||||||
scanner-web:
|
scanner-web:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:3df8ca21878126758203c1a0444e39fd97f77ddacf04a69685cda9f1e5e94718
|
image: registry.stella-ops.org/stellaops/scanner-web@sha256:3df8ca21878126758203c1a0444e39fd97f77ddacf04a69685cda9f1e5e94718
|
||||||
service:
|
service:
|
||||||
port: 8444
|
port: 8444
|
||||||
env:
|
env:
|
||||||
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
@@ -110,8 +110,12 @@ services:
|
|||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER: "file"
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT: "/etc/stellaops/secrets"
|
||||||
scanner-worker:
|
scanner-worker:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:eea5d6cfe7835950c5ec7a735a651f2f0d727d3e470cf9027a4a402ea89c4fb5
|
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:eea5d6cfe7835950c5ec7a735a651f2f0d727d3e470cf9027a4a402ea89c4fb5
|
||||||
env:
|
env:
|
||||||
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
@@ -125,62 +129,66 @@ services:
|
|||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
notify-web:
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
service:
|
SCANNER_SURFACE_SECRETS_PROVIDER: "file"
|
||||||
port: 8446
|
SCANNER_SURFACE_SECRETS_ROOT: "/etc/stellaops/secrets"
|
||||||
env:
|
notify-web:
|
||||||
DOTNET_ENVIRONMENT: Production
|
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
|
||||||
configMounts:
|
service:
|
||||||
- name: notify-config
|
port: 8446
|
||||||
mountPath: /app/etc/notify.yaml
|
env:
|
||||||
subPath: notify.yaml
|
DOTNET_ENVIRONMENT: Production
|
||||||
configMap: notify-config
|
configMounts:
|
||||||
excititor:
|
- name: notify-config
|
||||||
image: registry.stella-ops.org/stellaops/excititor@sha256:65c0ee13f773efe920d7181512349a09d363ab3f3e177d276136bd2742325a68
|
mountPath: /app/etc/notify.yaml
|
||||||
env:
|
subPath: notify.yaml
|
||||||
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
configMap: notify-config
|
||||||
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
excititor:
|
||||||
web-ui:
|
image: registry.stella-ops.org/stellaops/excititor@sha256:65c0ee13f773efe920d7181512349a09d363ab3f3e177d276136bd2742325a68
|
||||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:bee9668011ff414572131dc777faab4da24473fe12c230893f161cabee092a1d
|
env:
|
||||||
service:
|
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
||||||
port: 9443
|
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-airgap:stellaops-airgap@stellaops-mongo:27017"
|
||||||
targetPort: 8443
|
web-ui:
|
||||||
env:
|
image: registry.stella-ops.org/stellaops/web-ui@sha256:bee9668011ff414572131dc777faab4da24473fe12c230893f161cabee092a1d
|
||||||
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
service:
|
||||||
mongo:
|
port: 9443
|
||||||
class: infrastructure
|
targetPort: 8443
|
||||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
env:
|
||||||
service:
|
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
||||||
port: 27017
|
mongo:
|
||||||
command:
|
class: infrastructure
|
||||||
- mongod
|
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||||
- --bind_ip_all
|
service:
|
||||||
env:
|
port: 27017
|
||||||
MONGO_INITDB_ROOT_USERNAME: stellaops-airgap
|
command:
|
||||||
MONGO_INITDB_ROOT_PASSWORD: stellaops-airgap
|
- mongod
|
||||||
volumeMounts:
|
- --bind_ip_all
|
||||||
- name: mongo-data
|
env:
|
||||||
mountPath: /data/db
|
MONGO_INITDB_ROOT_USERNAME: stellaops-airgap
|
||||||
volumeClaims:
|
MONGO_INITDB_ROOT_PASSWORD: stellaops-airgap
|
||||||
- name: mongo-data
|
volumeMounts:
|
||||||
claimName: stellaops-mongo-data
|
- name: mongo-data
|
||||||
|
mountPath: /data/db
|
||||||
|
volumeClaims:
|
||||||
|
- name: mongo-data
|
||||||
|
claimName: stellaops-mongo-data
|
||||||
minio:
|
minio:
|
||||||
class: infrastructure
|
class: infrastructure
|
||||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||||
service:
|
service:
|
||||||
port: 9000
|
port: 9000
|
||||||
command:
|
command:
|
||||||
- server
|
- server
|
||||||
- /data
|
- /data
|
||||||
- --console-address
|
- --console-address
|
||||||
- :9001
|
- :9001
|
||||||
env:
|
env:
|
||||||
MINIO_ROOT_USER: stellaops-airgap
|
MINIO_ROOT_USER: stellaops-airgap
|
||||||
MINIO_ROOT_PASSWORD: airgap-minio-secret
|
MINIO_ROOT_PASSWORD: airgap-minio-secret
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: minio-data
|
- name: minio-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: minio-data
|
- name: minio-data
|
||||||
claimName: stellaops-minio-data
|
claimName: stellaops-minio-data
|
||||||
@@ -204,18 +212,18 @@ services:
|
|||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: rustfs-data
|
- name: rustfs-data
|
||||||
claimName: stellaops-rustfs-data
|
claimName: stellaops-rustfs-data
|
||||||
nats:
|
nats:
|
||||||
class: infrastructure
|
class: infrastructure
|
||||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||||
service:
|
service:
|
||||||
port: 4222
|
port: 4222
|
||||||
command:
|
command:
|
||||||
- -js
|
- -js
|
||||||
- -sd
|
- -sd
|
||||||
- /data
|
- /data
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: nats-data
|
- name: nats-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: nats-data
|
- name: nats-data
|
||||||
claimName: stellaops-nats-data
|
claimName: stellaops-nats-data
|
||||||
|
|||||||
@@ -17,92 +17,92 @@ telemetry:
|
|||||||
secretName: stellaops-otel-tls
|
secretName: stellaops-otel-tls
|
||||||
|
|
||||||
configMaps:
|
configMaps:
|
||||||
notify-config:
|
notify-config:
|
||||||
data:
|
data:
|
||||||
notify.yaml: |
|
notify.yaml: |
|
||||||
storage:
|
storage:
|
||||||
driver: mongo
|
driver: mongo
|
||||||
connectionString: "mongodb://notify-mongo.dev.svc.cluster.local:27017"
|
connectionString: "mongodb://notify-mongo.dev.svc.cluster.local:27017"
|
||||||
database: "stellaops_notify_dev"
|
database: "stellaops_notify_dev"
|
||||||
commandTimeoutSeconds: 30
|
commandTimeoutSeconds: 30
|
||||||
|
|
||||||
authority:
|
authority:
|
||||||
enabled: true
|
enabled: true
|
||||||
issuer: "https://authority.dev.stella-ops.local"
|
issuer: "https://authority.dev.stella-ops.local"
|
||||||
metadataAddress: "https://authority.dev.stella-ops.local/.well-known/openid-configuration"
|
metadataAddress: "https://authority.dev.stella-ops.local/.well-known/openid-configuration"
|
||||||
requireHttpsMetadata: false
|
requireHttpsMetadata: false
|
||||||
allowAnonymousFallback: false
|
allowAnonymousFallback: false
|
||||||
backchannelTimeoutSeconds: 30
|
backchannelTimeoutSeconds: 30
|
||||||
tokenClockSkewSeconds: 60
|
tokenClockSkewSeconds: 60
|
||||||
audiences:
|
audiences:
|
||||||
- notify.dev
|
- notify.dev
|
||||||
readScope: notify.read
|
readScope: notify.read
|
||||||
adminScope: notify.admin
|
adminScope: notify.admin
|
||||||
|
|
||||||
api:
|
api:
|
||||||
basePath: "/api/v1/notify"
|
basePath: "/api/v1/notify"
|
||||||
internalBasePath: "/internal/notify"
|
internalBasePath: "/internal/notify"
|
||||||
tenantHeader: "X-StellaOps-Tenant"
|
tenantHeader: "X-StellaOps-Tenant"
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
baseDirectory: "../"
|
baseDirectory: "../"
|
||||||
directory: "plugins/notify"
|
directory: "plugins/notify"
|
||||||
searchPatterns:
|
searchPatterns:
|
||||||
- "StellaOps.Notify.Connectors.*.dll"
|
- "StellaOps.Notify.Connectors.*.dll"
|
||||||
orderedPlugins:
|
orderedPlugins:
|
||||||
- StellaOps.Notify.Connectors.Slack
|
- StellaOps.Notify.Connectors.Slack
|
||||||
- StellaOps.Notify.Connectors.Teams
|
- StellaOps.Notify.Connectors.Teams
|
||||||
- StellaOps.Notify.Connectors.Email
|
- StellaOps.Notify.Connectors.Email
|
||||||
- StellaOps.Notify.Connectors.Webhook
|
- StellaOps.Notify.Connectors.Webhook
|
||||||
|
|
||||||
telemetry:
|
telemetry:
|
||||||
enableRequestLogging: true
|
enableRequestLogging: true
|
||||||
minimumLogLevel: Debug
|
minimumLogLevel: Debug
|
||||||
services:
|
services:
|
||||||
authority:
|
authority:
|
||||||
image: registry.stella-ops.org/stellaops/authority@sha256:a8e8faec44a579aa5714e58be835f25575710430b1ad2ccd1282a018cd9ffcdd
|
image: registry.stella-ops.org/stellaops/authority@sha256:a8e8faec44a579aa5714e58be835f25575710430b1ad2ccd1282a018cd9ffcdd
|
||||||
service:
|
service:
|
||||||
port: 8440
|
port: 8440
|
||||||
env:
|
env:
|
||||||
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
|
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
|
||||||
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||||
signer:
|
signer:
|
||||||
image: registry.stella-ops.org/stellaops/signer@sha256:8bfef9a75783883d49fc18e3566553934e970b00ee090abee9cb110d2d5c3298
|
image: registry.stella-ops.org/stellaops/signer@sha256:8bfef9a75783883d49fc18e3566553934e970b00ee090abee9cb110d2d5c3298
|
||||||
service:
|
service:
|
||||||
port: 8441
|
port: 8441
|
||||||
env:
|
env:
|
||||||
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
SIGNER__POE__INTROSPECTURL: "https://licensing.svc.local/introspect"
|
SIGNER__POE__INTROSPECTURL: "https://licensing.svc.local/introspect"
|
||||||
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
attestor:
|
attestor:
|
||||||
image: registry.stella-ops.org/stellaops/attestor@sha256:5cc417948c029da01dccf36e4645d961a3f6d8de7e62fe98d845f07cd2282114
|
image: registry.stella-ops.org/stellaops/attestor@sha256:5cc417948c029da01dccf36e4645d961a3f6d8de7e62fe98d845f07cd2282114
|
||||||
service:
|
service:
|
||||||
port: 8442
|
port: 8442
|
||||||
env:
|
env:
|
||||||
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
||||||
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
concelier:
|
concelier:
|
||||||
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
|
image: registry.stella-ops.org/stellaops/concelier@sha256:dafef3954eb4b837e2c424dd2d23e1e4d60fa83794840fac9cd3dea1d43bd085
|
||||||
service:
|
service:
|
||||||
port: 8445
|
port: 8445
|
||||||
env:
|
env:
|
||||||
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
||||||
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops"
|
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops"
|
||||||
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "dev-minio-secret"
|
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "dev-minio-secret"
|
||||||
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
mountPath: /var/lib/concelier/jobs
|
mountPath: /var/lib/concelier/jobs
|
||||||
volumes:
|
volumes:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
scanner-web:
|
scanner-web:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:e0dfdb087e330585a5953029fb4757f5abdf7610820a085bd61b457dbead9a11
|
image: registry.stella-ops.org/stellaops/scanner-web@sha256:e0dfdb087e330585a5953029fb4757f5abdf7610820a085bd61b457dbead9a11
|
||||||
service:
|
service:
|
||||||
port: 8444
|
port: 8444
|
||||||
env:
|
env:
|
||||||
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
@@ -116,8 +116,12 @@ services:
|
|||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER: "inline"
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT: ""
|
||||||
scanner-worker:
|
scanner-worker:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:92dda42f6f64b2d9522104a5c9ffb61d37b34dd193132b68457a259748008f37
|
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:92dda42f6f64b2d9522104a5c9ffb61d37b34dd193132b68457a259748008f37
|
||||||
env:
|
env:
|
||||||
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
@@ -131,61 +135,65 @@ services:
|
|||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
notify-web:
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
image: registry.stella-ops.org/stellaops/notify-web:2025.10.0-edge
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
service:
|
SCANNER_SURFACE_SECRETS_PROVIDER: "inline"
|
||||||
port: 8446
|
SCANNER_SURFACE_SECRETS_ROOT: ""
|
||||||
env:
|
notify-web:
|
||||||
DOTNET_ENVIRONMENT: Development
|
image: registry.stella-ops.org/stellaops/notify-web:2025.10.0-edge
|
||||||
configMounts:
|
service:
|
||||||
- name: notify-config
|
port: 8446
|
||||||
mountPath: /app/etc/notify.yaml
|
env:
|
||||||
subPath: notify.yaml
|
DOTNET_ENVIRONMENT: Development
|
||||||
configMap: notify-config
|
configMounts:
|
||||||
excititor:
|
- name: notify-config
|
||||||
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
|
mountPath: /app/etc/notify.yaml
|
||||||
env:
|
subPath: notify.yaml
|
||||||
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
configMap: notify-config
|
||||||
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
excititor:
|
||||||
web-ui:
|
image: registry.stella-ops.org/stellaops/excititor@sha256:d9bd5cadf1eab427447ce3df7302c30ded837239771cc6433b9befb895054285
|
||||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:38b225fa7767a5b94ebae4dae8696044126aac429415e93de514d5dd95748dcf
|
env:
|
||||||
service:
|
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
||||||
port: 8443
|
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops:stellaops@stellaops-mongo:27017"
|
||||||
env:
|
web-ui:
|
||||||
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
image: registry.stella-ops.org/stellaops/web-ui@sha256:38b225fa7767a5b94ebae4dae8696044126aac429415e93de514d5dd95748dcf
|
||||||
mongo:
|
service:
|
||||||
class: infrastructure
|
port: 8443
|
||||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
env:
|
||||||
service:
|
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
||||||
port: 27017
|
mongo:
|
||||||
command:
|
class: infrastructure
|
||||||
- mongod
|
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||||
- --bind_ip_all
|
service:
|
||||||
env:
|
port: 27017
|
||||||
MONGO_INITDB_ROOT_USERNAME: stellaops
|
command:
|
||||||
MONGO_INITDB_ROOT_PASSWORD: stellaops
|
- mongod
|
||||||
volumeMounts:
|
- --bind_ip_all
|
||||||
- name: mongo-data
|
env:
|
||||||
mountPath: /data/db
|
MONGO_INITDB_ROOT_USERNAME: stellaops
|
||||||
volumes:
|
MONGO_INITDB_ROOT_PASSWORD: stellaops
|
||||||
- name: mongo-data
|
volumeMounts:
|
||||||
emptyDir: {}
|
- name: mongo-data
|
||||||
|
mountPath: /data/db
|
||||||
|
volumes:
|
||||||
|
- name: mongo-data
|
||||||
|
emptyDir: {}
|
||||||
minio:
|
minio:
|
||||||
class: infrastructure
|
class: infrastructure
|
||||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||||
service:
|
service:
|
||||||
port: 9000
|
port: 9000
|
||||||
command:
|
command:
|
||||||
- server
|
- server
|
||||||
- /data
|
- /data
|
||||||
- --console-address
|
- --console-address
|
||||||
- :9001
|
- :9001
|
||||||
env:
|
env:
|
||||||
MINIO_ROOT_USER: stellaops
|
MINIO_ROOT_USER: stellaops
|
||||||
MINIO_ROOT_PASSWORD: dev-minio-secret
|
MINIO_ROOT_PASSWORD: dev-minio-secret
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: minio-data
|
- name: minio-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
volumes:
|
volumes:
|
||||||
- name: minio-data
|
- name: minio-data
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
@@ -203,18 +211,18 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- name: rustfs-data
|
- name: rustfs-data
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
nats:
|
nats:
|
||||||
class: infrastructure
|
class: infrastructure
|
||||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||||
service:
|
service:
|
||||||
port: 4222
|
port: 4222
|
||||||
command:
|
command:
|
||||||
- -js
|
- -js
|
||||||
- -sd
|
- -sd
|
||||||
- /data
|
- /data
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: nats-data
|
- name: nats-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
volumes:
|
volumes:
|
||||||
- name: nats-data
|
- name: nats-data
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
|
|||||||
@@ -1,221 +1,229 @@
|
|||||||
global:
|
global:
|
||||||
profile: prod
|
profile: prod
|
||||||
release:
|
release:
|
||||||
version: "2025.09.2"
|
version: "2025.09.2"
|
||||||
channel: stable
|
channel: stable
|
||||||
manifestSha256: "dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
|
manifestSha256: "dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
|
||||||
image:
|
image:
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
labels:
|
labels:
|
||||||
stellaops.io/channel: stable
|
stellaops.io/channel: stable
|
||||||
stellaops.io/profile: prod
|
stellaops.io/profile: prod
|
||||||
|
|
||||||
configMaps:
|
configMaps:
|
||||||
notify-config:
|
notify-config:
|
||||||
data:
|
data:
|
||||||
notify.yaml: |
|
notify.yaml: |
|
||||||
storage:
|
storage:
|
||||||
driver: mongo
|
driver: mongo
|
||||||
connectionString: "mongodb://stellaops-mongo:27017"
|
connectionString: "mongodb://stellaops-mongo:27017"
|
||||||
database: "stellaops_notify_prod"
|
database: "stellaops_notify_prod"
|
||||||
commandTimeoutSeconds: 45
|
commandTimeoutSeconds: 45
|
||||||
|
|
||||||
authority:
|
authority:
|
||||||
enabled: true
|
enabled: true
|
||||||
issuer: "https://authority.prod.stella-ops.org"
|
issuer: "https://authority.prod.stella-ops.org"
|
||||||
metadataAddress: "https://authority.prod.stella-ops.org/.well-known/openid-configuration"
|
metadataAddress: "https://authority.prod.stella-ops.org/.well-known/openid-configuration"
|
||||||
requireHttpsMetadata: true
|
requireHttpsMetadata: true
|
||||||
allowAnonymousFallback: false
|
allowAnonymousFallback: false
|
||||||
backchannelTimeoutSeconds: 30
|
backchannelTimeoutSeconds: 30
|
||||||
tokenClockSkewSeconds: 60
|
tokenClockSkewSeconds: 60
|
||||||
audiences:
|
audiences:
|
||||||
- notify
|
- notify
|
||||||
readScope: notify.read
|
readScope: notify.read
|
||||||
adminScope: notify.admin
|
adminScope: notify.admin
|
||||||
|
|
||||||
api:
|
api:
|
||||||
basePath: "/api/v1/notify"
|
basePath: "/api/v1/notify"
|
||||||
internalBasePath: "/internal/notify"
|
internalBasePath: "/internal/notify"
|
||||||
tenantHeader: "X-StellaOps-Tenant"
|
tenantHeader: "X-StellaOps-Tenant"
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
baseDirectory: "/opt/stellaops"
|
baseDirectory: "/opt/stellaops"
|
||||||
directory: "plugins/notify"
|
directory: "plugins/notify"
|
||||||
searchPatterns:
|
searchPatterns:
|
||||||
- "StellaOps.Notify.Connectors.*.dll"
|
- "StellaOps.Notify.Connectors.*.dll"
|
||||||
orderedPlugins:
|
orderedPlugins:
|
||||||
- StellaOps.Notify.Connectors.Slack
|
- StellaOps.Notify.Connectors.Slack
|
||||||
- StellaOps.Notify.Connectors.Teams
|
- StellaOps.Notify.Connectors.Teams
|
||||||
- StellaOps.Notify.Connectors.Email
|
- StellaOps.Notify.Connectors.Email
|
||||||
- StellaOps.Notify.Connectors.Webhook
|
- StellaOps.Notify.Connectors.Webhook
|
||||||
|
|
||||||
telemetry:
|
telemetry:
|
||||||
enableRequestLogging: true
|
enableRequestLogging: true
|
||||||
minimumLogLevel: Information
|
minimumLogLevel: Information
|
||||||
services:
|
services:
|
||||||
authority:
|
authority:
|
||||||
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
||||||
service:
|
service:
|
||||||
port: 8440
|
port: 8440
|
||||||
env:
|
env:
|
||||||
STELLAOPS_AUTHORITY__ISSUER: "https://authority.prod.stella-ops.org"
|
STELLAOPS_AUTHORITY__ISSUER: "https://authority.prod.stella-ops.org"
|
||||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: stellaops-prod-core
|
name: stellaops-prod-core
|
||||||
signer:
|
signer:
|
||||||
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
||||||
service:
|
service:
|
||||||
port: 8441
|
port: 8441
|
||||||
env:
|
env:
|
||||||
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
SIGNER__POE__INTROSPECTURL: "https://licensing.prod.stella-ops.org/introspect"
|
SIGNER__POE__INTROSPECTURL: "https://licensing.prod.stella-ops.org/introspect"
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: stellaops-prod-core
|
name: stellaops-prod-core
|
||||||
attestor:
|
attestor:
|
||||||
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
||||||
service:
|
service:
|
||||||
port: 8442
|
port: 8442
|
||||||
env:
|
env:
|
||||||
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: stellaops-prod-core
|
name: stellaops-prod-core
|
||||||
concelier:
|
concelier:
|
||||||
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
||||||
service:
|
service:
|
||||||
port: 8445
|
port: 8445
|
||||||
env:
|
env:
|
||||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
||||||
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: stellaops-prod-core
|
name: stellaops-prod-core
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
mountPath: /var/lib/concelier/jobs
|
mountPath: /var/lib/concelier/jobs
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
claimName: stellaops-concelier-jobs
|
claimName: stellaops-concelier-jobs
|
||||||
scanner-web:
|
scanner-web:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
||||||
service:
|
service:
|
||||||
port: 8444
|
port: 8444
|
||||||
env:
|
env:
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||||
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
|
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
|
||||||
SCANNER__EVENTS__ENABLED: "true"
|
SCANNER__EVENTS__ENABLED: "true"
|
||||||
SCANNER__EVENTS__DRIVER: "redis"
|
SCANNER__EVENTS__DRIVER: "redis"
|
||||||
SCANNER__EVENTS__DSN: ""
|
SCANNER__EVENTS__DSN: ""
|
||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
envFrom:
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
- secretRef:
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
name: stellaops-prod-core
|
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
|
||||||
scanner-worker:
|
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
|
||||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
envFrom:
|
||||||
replicas: 3
|
- secretRef:
|
||||||
env:
|
name: stellaops-prod-core
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
scanner-worker:
|
||||||
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
||||||
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
replicas: 3
|
||||||
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
env:
|
||||||
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
SCANNER__EVENTS__ENABLED: "true"
|
SCANNER__ARTIFACTSTORE__ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
SCANNER__EVENTS__DRIVER: "redis"
|
SCANNER__ARTIFACTSTORE__BUCKET: "scanner-artifacts"
|
||||||
SCANNER__EVENTS__DSN: ""
|
SCANNER__ARTIFACTSTORE__TIMEOUTSECONDS: "30"
|
||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__QUEUE__BROKER: "nats://stellaops-nats:4222"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__ENABLED: "true"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__DRIVER: "redis"
|
||||||
envFrom:
|
SCANNER__EVENTS__DSN: ""
|
||||||
- secretRef:
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
name: stellaops-prod-core
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
notify-web:
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
service:
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
port: 8446
|
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
|
||||||
env:
|
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
|
||||||
DOTNET_ENVIRONMENT: Production
|
envFrom:
|
||||||
envFrom:
|
- secretRef:
|
||||||
- secretRef:
|
name: stellaops-prod-core
|
||||||
name: stellaops-prod-notify
|
notify-web:
|
||||||
configMounts:
|
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
|
||||||
- name: notify-config
|
service:
|
||||||
mountPath: /app/etc/notify.yaml
|
port: 8446
|
||||||
subPath: notify.yaml
|
env:
|
||||||
configMap: notify-config
|
DOTNET_ENVIRONMENT: Production
|
||||||
excititor:
|
envFrom:
|
||||||
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
- secretRef:
|
||||||
env:
|
name: stellaops-prod-notify
|
||||||
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
configMounts:
|
||||||
envFrom:
|
- name: notify-config
|
||||||
- secretRef:
|
mountPath: /app/etc/notify.yaml
|
||||||
name: stellaops-prod-core
|
subPath: notify.yaml
|
||||||
web-ui:
|
configMap: notify-config
|
||||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
excititor:
|
||||||
service:
|
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
||||||
port: 8443
|
env:
|
||||||
env:
|
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
||||||
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
envFrom:
|
||||||
mongo:
|
- secretRef:
|
||||||
class: infrastructure
|
name: stellaops-prod-core
|
||||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
web-ui:
|
||||||
service:
|
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
||||||
port: 27017
|
service:
|
||||||
command:
|
port: 8443
|
||||||
- mongod
|
env:
|
||||||
- --bind_ip_all
|
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
||||||
envFrom:
|
mongo:
|
||||||
- secretRef:
|
class: infrastructure
|
||||||
name: stellaops-prod-mongo
|
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||||
volumeMounts:
|
service:
|
||||||
- name: mongo-data
|
port: 27017
|
||||||
mountPath: /data/db
|
command:
|
||||||
volumeClaims:
|
- mongod
|
||||||
- name: mongo-data
|
- --bind_ip_all
|
||||||
claimName: stellaops-mongo-data
|
envFrom:
|
||||||
minio:
|
- secretRef:
|
||||||
class: infrastructure
|
name: stellaops-prod-mongo
|
||||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
volumeMounts:
|
||||||
service:
|
- name: mongo-data
|
||||||
port: 9000
|
mountPath: /data/db
|
||||||
command:
|
volumeClaims:
|
||||||
- server
|
- name: mongo-data
|
||||||
- /data
|
claimName: stellaops-mongo-data
|
||||||
- --console-address
|
minio:
|
||||||
- :9001
|
class: infrastructure
|
||||||
envFrom:
|
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||||
- secretRef:
|
service:
|
||||||
name: stellaops-prod-minio
|
port: 9000
|
||||||
volumeMounts:
|
command:
|
||||||
- name: minio-data
|
- server
|
||||||
mountPath: /data
|
- /data
|
||||||
volumeClaims:
|
- --console-address
|
||||||
- name: minio-data
|
- :9001
|
||||||
claimName: stellaops-minio-data
|
envFrom:
|
||||||
rustfs:
|
- secretRef:
|
||||||
class: infrastructure
|
name: stellaops-prod-minio
|
||||||
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
volumeMounts:
|
||||||
service:
|
- name: minio-data
|
||||||
port: 8080
|
mountPath: /data
|
||||||
command:
|
volumeClaims:
|
||||||
- serve
|
- name: minio-data
|
||||||
- --listen
|
claimName: stellaops-minio-data
|
||||||
- 0.0.0.0:8080
|
rustfs:
|
||||||
- --root
|
class: infrastructure
|
||||||
- /data
|
image: registry.stella-ops.org/stellaops/rustfs:2025.10.0-edge
|
||||||
env:
|
service:
|
||||||
RUSTFS__LOG__LEVEL: info
|
port: 8080
|
||||||
RUSTFS__STORAGE__PATH: /data
|
command:
|
||||||
volumeMounts:
|
- serve
|
||||||
- name: rustfs-data
|
- --listen
|
||||||
mountPath: /data
|
- 0.0.0.0:8080
|
||||||
volumeClaims:
|
- --root
|
||||||
- name: rustfs-data
|
- /data
|
||||||
claimName: stellaops-rustfs-data
|
env:
|
||||||
|
RUSTFS__LOG__LEVEL: info
|
||||||
|
RUSTFS__STORAGE__PATH: /data
|
||||||
|
volumeMounts:
|
||||||
|
- name: rustfs-data
|
||||||
|
mountPath: /data
|
||||||
|
volumeClaims:
|
||||||
|
- name: rustfs-data
|
||||||
|
claimName: stellaops-rustfs-data
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ global:
|
|||||||
profile: stage
|
profile: stage
|
||||||
release:
|
release:
|
||||||
version: "2025.09.2"
|
version: "2025.09.2"
|
||||||
channel: stable
|
channel: stable
|
||||||
manifestSha256: "dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
|
manifestSha256: "dc3c8fe1ab83941c838ccc5a8a5862f7ddfa38c2078e580b5649db26554565b7"
|
||||||
image:
|
image:
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
labels:
|
labels:
|
||||||
stellaops.io/channel: stable
|
stellaops.io/channel: stable
|
||||||
|
|
||||||
@@ -15,94 +15,94 @@ telemetry:
|
|||||||
defaultTenant: stage
|
defaultTenant: stage
|
||||||
tls:
|
tls:
|
||||||
secretName: stellaops-otel-tls-stage
|
secretName: stellaops-otel-tls-stage
|
||||||
|
|
||||||
configMaps:
|
configMaps:
|
||||||
notify-config:
|
notify-config:
|
||||||
data:
|
data:
|
||||||
notify.yaml: |
|
notify.yaml: |
|
||||||
storage:
|
storage:
|
||||||
driver: mongo
|
driver: mongo
|
||||||
connectionString: "mongodb://notify-mongo.stage.svc.cluster.local:27017"
|
connectionString: "mongodb://notify-mongo.stage.svc.cluster.local:27017"
|
||||||
database: "stellaops_notify_stage"
|
database: "stellaops_notify_stage"
|
||||||
commandTimeoutSeconds: 45
|
commandTimeoutSeconds: 45
|
||||||
|
|
||||||
authority:
|
authority:
|
||||||
enabled: true
|
enabled: true
|
||||||
issuer: "https://authority.stage.stella-ops.org"
|
issuer: "https://authority.stage.stella-ops.org"
|
||||||
metadataAddress: "https://authority.stage.stella-ops.org/.well-known/openid-configuration"
|
metadataAddress: "https://authority.stage.stella-ops.org/.well-known/openid-configuration"
|
||||||
requireHttpsMetadata: true
|
requireHttpsMetadata: true
|
||||||
allowAnonymousFallback: false
|
allowAnonymousFallback: false
|
||||||
backchannelTimeoutSeconds: 30
|
backchannelTimeoutSeconds: 30
|
||||||
tokenClockSkewSeconds: 60
|
tokenClockSkewSeconds: 60
|
||||||
audiences:
|
audiences:
|
||||||
- notify
|
- notify
|
||||||
readScope: notify.read
|
readScope: notify.read
|
||||||
adminScope: notify.admin
|
adminScope: notify.admin
|
||||||
|
|
||||||
api:
|
api:
|
||||||
basePath: "/api/v1/notify"
|
basePath: "/api/v1/notify"
|
||||||
internalBasePath: "/internal/notify"
|
internalBasePath: "/internal/notify"
|
||||||
tenantHeader: "X-StellaOps-Tenant"
|
tenantHeader: "X-StellaOps-Tenant"
|
||||||
|
|
||||||
plugins:
|
plugins:
|
||||||
baseDirectory: "/opt/stellaops"
|
baseDirectory: "/opt/stellaops"
|
||||||
directory: "plugins/notify"
|
directory: "plugins/notify"
|
||||||
searchPatterns:
|
searchPatterns:
|
||||||
- "StellaOps.Notify.Connectors.*.dll"
|
- "StellaOps.Notify.Connectors.*.dll"
|
||||||
orderedPlugins:
|
orderedPlugins:
|
||||||
- StellaOps.Notify.Connectors.Slack
|
- StellaOps.Notify.Connectors.Slack
|
||||||
- StellaOps.Notify.Connectors.Teams
|
- StellaOps.Notify.Connectors.Teams
|
||||||
- StellaOps.Notify.Connectors.Email
|
- StellaOps.Notify.Connectors.Email
|
||||||
- StellaOps.Notify.Connectors.Webhook
|
- StellaOps.Notify.Connectors.Webhook
|
||||||
|
|
||||||
telemetry:
|
telemetry:
|
||||||
enableRequestLogging: true
|
enableRequestLogging: true
|
||||||
minimumLogLevel: Information
|
minimumLogLevel: Information
|
||||||
services:
|
services:
|
||||||
authority:
|
authority:
|
||||||
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
image: registry.stella-ops.org/stellaops/authority@sha256:b0348bad1d0b401cc3c71cb40ba034c8043b6c8874546f90d4783c9dbfcc0bf5
|
||||||
service:
|
service:
|
||||||
port: 8440
|
port: 8440
|
||||||
env:
|
env:
|
||||||
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
|
STELLAOPS_AUTHORITY__ISSUER: "https://stellaops-authority:8440"
|
||||||
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
STELLAOPS_AUTHORITY__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
STELLAOPS_AUTHORITY__PLUGINDIRECTORIES__0: "/app/plugins"
|
||||||
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
STELLAOPS_AUTHORITY__PLUGINS__CONFIGURATIONDIRECTORY: "/app/etc/authority.plugins"
|
||||||
signer:
|
signer:
|
||||||
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
image: registry.stella-ops.org/stellaops/signer@sha256:8ad574e61f3a9e9bda8a58eb2700ae46813284e35a150b1137bc7c2b92ac0f2e
|
||||||
service:
|
service:
|
||||||
port: 8441
|
port: 8441
|
||||||
env:
|
env:
|
||||||
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
SIGNER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
SIGNER__POE__INTROSPECTURL: "https://licensing.stage.stella-ops.internal/introspect"
|
SIGNER__POE__INTROSPECTURL: "https://licensing.stage.stella-ops.internal/introspect"
|
||||||
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
SIGNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
attestor:
|
attestor:
|
||||||
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
image: registry.stella-ops.org/stellaops/attestor@sha256:0534985f978b0b5d220d73c96fddd962cd9135f616811cbe3bff4666c5af568f
|
||||||
service:
|
service:
|
||||||
port: 8442
|
port: 8442
|
||||||
env:
|
env:
|
||||||
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
ATTESTOR__SIGNER__BASEURL: "https://stellaops-signer:8441"
|
||||||
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
ATTESTOR__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
concelier:
|
concelier:
|
||||||
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
image: registry.stella-ops.org/stellaops/concelier@sha256:c58cdcaee1d266d68d498e41110a589dd204b487d37381096bd61ab345a867c5
|
||||||
service:
|
service:
|
||||||
port: 8445
|
port: 8445
|
||||||
env:
|
env:
|
||||||
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
CONCELIER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
CONCELIER__STORAGE__S3__ENDPOINT: "http://stellaops-minio:9000"
|
||||||
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-stage"
|
CONCELIER__STORAGE__S3__ACCESSKEYID: "stellaops-stage"
|
||||||
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "stage-minio-secret"
|
CONCELIER__STORAGE__S3__SECRETACCESSKEY: "stage-minio-secret"
|
||||||
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
CONCELIER__AUTHORITY__BASEURL: "https://stellaops-authority:8440"
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
mountPath: /var/lib/concelier/jobs
|
mountPath: /var/lib/concelier/jobs
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: concelier-jobs
|
- name: concelier-jobs
|
||||||
claimName: stellaops-concelier-jobs
|
claimName: stellaops-concelier-jobs
|
||||||
scanner-web:
|
scanner-web:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
image: registry.stella-ops.org/stellaops/scanner-web@sha256:14b23448c3f9586a9156370b3e8c1991b61907efa666ca37dd3aaed1e79fe3b7
|
||||||
service:
|
service:
|
||||||
port: 8444
|
port: 8444
|
||||||
env:
|
env:
|
||||||
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
@@ -116,9 +116,13 @@ services:
|
|||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
|
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
|
||||||
|
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
|
||||||
scanner-worker:
|
scanner-worker:
|
||||||
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
image: registry.stella-ops.org/stellaops/scanner-worker@sha256:32e25e76386eb9ea8bee0a1ad546775db9a2df989fab61ac877e351881960dab
|
||||||
replicas: 2
|
replicas: 2
|
||||||
env:
|
env:
|
||||||
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
SCANNER__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
SCANNER__ARTIFACTSTORE__DRIVER: "rustfs"
|
||||||
@@ -132,61 +136,65 @@ services:
|
|||||||
SCANNER__EVENTS__STREAM: "stella.events"
|
SCANNER__EVENTS__STREAM: "stella.events"
|
||||||
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
SCANNER__EVENTS__PUBLISHTIMEOUTSECONDS: "5"
|
||||||
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
SCANNER__EVENTS__MAXSTREAMLENGTH: "10000"
|
||||||
notify-web:
|
SCANNER_SURFACE_FS_ENDPOINT: "http://stellaops-rustfs:8080/api/v1"
|
||||||
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
|
SCANNER_SURFACE_CACHE_ROOT: "/var/lib/stellaops/surface"
|
||||||
service:
|
SCANNER_SURFACE_SECRETS_PROVIDER: "kubernetes"
|
||||||
port: 8446
|
SCANNER_SURFACE_SECRETS_ROOT: "stellaops/scanner"
|
||||||
env:
|
notify-web:
|
||||||
DOTNET_ENVIRONMENT: Production
|
image: registry.stella-ops.org/stellaops/notify-web:2025.09.2
|
||||||
configMounts:
|
service:
|
||||||
- name: notify-config
|
port: 8446
|
||||||
mountPath: /app/etc/notify.yaml
|
env:
|
||||||
subPath: notify.yaml
|
DOTNET_ENVIRONMENT: Production
|
||||||
configMap: notify-config
|
configMounts:
|
||||||
excititor:
|
- name: notify-config
|
||||||
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
mountPath: /app/etc/notify.yaml
|
||||||
env:
|
subPath: notify.yaml
|
||||||
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
configMap: notify-config
|
||||||
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
excititor:
|
||||||
web-ui:
|
image: registry.stella-ops.org/stellaops/excititor@sha256:59022e2016aebcef5c856d163ae705755d3f81949d41195256e935ef40a627fa
|
||||||
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
env:
|
||||||
service:
|
EXCITITOR__CONCELIER__BASEURL: "https://stellaops-concelier:8445"
|
||||||
port: 8443
|
EXCITITOR__STORAGE__MONGO__CONNECTIONSTRING: "mongodb://stellaops-stage:stellaops-stage@stellaops-mongo:27017"
|
||||||
env:
|
web-ui:
|
||||||
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
image: registry.stella-ops.org/stellaops/web-ui@sha256:10d924808c48e4353e3a241da62eb7aefe727a1d6dc830eb23a8e181013b3a23
|
||||||
mongo:
|
service:
|
||||||
class: infrastructure
|
port: 8443
|
||||||
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
env:
|
||||||
service:
|
STELLAOPS_UI__BACKEND__BASEURL: "https://stellaops-scanner-web:8444"
|
||||||
port: 27017
|
mongo:
|
||||||
command:
|
class: infrastructure
|
||||||
- mongod
|
image: docker.io/library/mongo@sha256:c258b26dbb7774f97f52aff52231ca5f228273a84329c5f5e451c3739457db49
|
||||||
- --bind_ip_all
|
service:
|
||||||
env:
|
port: 27017
|
||||||
MONGO_INITDB_ROOT_USERNAME: stellaops-stage
|
command:
|
||||||
MONGO_INITDB_ROOT_PASSWORD: stellaops-stage
|
- mongod
|
||||||
volumeMounts:
|
- --bind_ip_all
|
||||||
- name: mongo-data
|
env:
|
||||||
mountPath: /data/db
|
MONGO_INITDB_ROOT_USERNAME: stellaops-stage
|
||||||
volumeClaims:
|
MONGO_INITDB_ROOT_PASSWORD: stellaops-stage
|
||||||
- name: mongo-data
|
volumeMounts:
|
||||||
claimName: stellaops-mongo-data
|
- name: mongo-data
|
||||||
|
mountPath: /data/db
|
||||||
|
volumeClaims:
|
||||||
|
- name: mongo-data
|
||||||
|
claimName: stellaops-mongo-data
|
||||||
minio:
|
minio:
|
||||||
class: infrastructure
|
class: infrastructure
|
||||||
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
image: docker.io/minio/minio@sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e
|
||||||
service:
|
service:
|
||||||
port: 9000
|
port: 9000
|
||||||
command:
|
command:
|
||||||
- server
|
- server
|
||||||
- /data
|
- /data
|
||||||
- --console-address
|
- --console-address
|
||||||
- :9001
|
- :9001
|
||||||
env:
|
env:
|
||||||
MINIO_ROOT_USER: stellaops-stage
|
MINIO_ROOT_USER: stellaops-stage
|
||||||
MINIO_ROOT_PASSWORD: stage-minio-secret
|
MINIO_ROOT_PASSWORD: stage-minio-secret
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: minio-data
|
- name: minio-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: minio-data
|
- name: minio-data
|
||||||
claimName: stellaops-minio-data
|
claimName: stellaops-minio-data
|
||||||
@@ -210,18 +218,18 @@ services:
|
|||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: rustfs-data
|
- name: rustfs-data
|
||||||
claimName: stellaops-rustfs-data
|
claimName: stellaops-rustfs-data
|
||||||
nats:
|
nats:
|
||||||
class: infrastructure
|
class: infrastructure
|
||||||
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
image: docker.io/library/nats@sha256:c82559e4476289481a8a5196e675ebfe67eea81d95e5161e3e78eccfe766608e
|
||||||
service:
|
service:
|
||||||
port: 4222
|
port: 4222
|
||||||
command:
|
command:
|
||||||
- -js
|
- -js
|
||||||
- -sd
|
- -sd
|
||||||
- /data
|
- /data
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: nats-data
|
- name: nats-data
|
||||||
mountPath: /data
|
mountPath: /data
|
||||||
volumeClaims:
|
volumeClaims:
|
||||||
- name: nats-data
|
- name: nats-data
|
||||||
claimName: stellaops-nats-data
|
claimName: stellaops-nats-data
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ EXCITITOR-AIRGAP-56-002 `Bundle provenance` | TODO | Persist bundle metadata on
|
|||||||
EXCITITOR-AIRGAP-57-001 `Sealed-mode enforcement` | TODO | Block non-mirror connectors in sealed mode and surface remediation errors. Dependencies: EXCITITOR-AIRGAP-56-002. | Excititor Core Guild, AirGap Policy Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
EXCITITOR-AIRGAP-57-001 `Sealed-mode enforcement` | TODO | Block non-mirror connectors in sealed mode and surface remediation errors. Dependencies: EXCITITOR-AIRGAP-56-002. | Excititor Core Guild, AirGap Policy Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
||||||
EXCITITOR-AIRGAP-57-002 `Staleness annotations` | TODO | Annotate VEX statements with staleness metrics and expose via API. Dependencies: EXCITITOR-AIRGAP-57-001. | Excititor Core Guild, AirGap Time Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
EXCITITOR-AIRGAP-57-002 `Staleness annotations` | TODO | Annotate VEX statements with staleness metrics and expose via API. Dependencies: EXCITITOR-AIRGAP-57-001. | Excititor Core Guild, AirGap Time Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
||||||
EXCITITOR-AIRGAP-58-001 `Portable VEX evidence` | TODO | Package VEX evidence segments into portable evidence bundles linked to timeline. Dependencies: EXCITITOR-AIRGAP-57-002. | Excititor Core Guild, Evidence Locker Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
EXCITITOR-AIRGAP-58-001 `Portable VEX evidence` | TODO | Package VEX evidence segments into portable evidence bundles linked to timeline. Dependencies: EXCITITOR-AIRGAP-57-002. | Excititor Core Guild, Evidence Locker Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
||||||
EXCITITOR-ATTEST-01-003 – Verification suite & observability | Team Excititor Attestation | 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.<br>2025-10-31: Verifier now tolerates duplicate source providers from AOC raw projections, downgrades offline Rekor verification to a degraded result, and enforces trusted signer registry checks with detailed diagnostics/tests.<br>2025-11-05 14:35Z: Resuming with diagnostics/observability deliverables (typed diagnostics record, ActivitySource wiring, metrics dimensions) before WebService/Worker integration. | EXCITITOR-ATTEST-01-002 (src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md)
|
EXCITITOR-ATTEST-01-003 – Verification suite & observability | Team Excititor Attestation | TODO (2025-11-06) – 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.<br>2025-10-31: Verifier now tolerates duplicate source providers from AOC raw projections, downgrades offline Rekor verification to a degraded result, and enforces trusted signer registry checks with detailed diagnostics/tests.<br>2025-11-05 14:35Z: Resuming with diagnostics/observability deliverables (typed diagnostics record, ActivitySource wiring, metrics dimensions) before WebService/Worker integration.<br>2025-11-06 07:12Z: Worker & web service suites pass with new diagnostics (`dotnet test` via staged libssl1.1); export envelope context exposed publicly for mirror bundle publishing.<br>2025-11-06 07:55Z: Paused—automation for OpenSSL shim tracked under `DEVOPS-OPENSSL-11-001/002`. | EXCITITOR-ATTEST-01-002 (src/Excititor/__Libraries/StellaOps.Excititor.Attestation/TASKS.md)
|
||||||
EXCITITOR-ATTEST-73-001 `VEX attestation payloads` | TODO | Provide VEX statement metadata (supplier identity, justification, scope) required for VEXAttestation payloads. Dependencies: EXCITITOR-ATTEST-01-003. | Excititor Core Guild, Attestation Payloads Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
EXCITITOR-ATTEST-73-001 `VEX attestation payloads` | TODO | Provide VEX statement metadata (supplier identity, justification, scope) required for VEXAttestation payloads. Dependencies: EXCITITOR-ATTEST-01-003. | Excititor Core Guild, Attestation Payloads Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
||||||
EXCITITOR-ATTEST-73-002 `Chain provenance` | TODO | Expose linkage from VEX statements to subject/product for chain of custody graph. Dependencies: EXCITITOR-ATTEST-73-001. | Excititor Core Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
EXCITITOR-ATTEST-73-002 `Chain provenance` | TODO | Expose linkage from VEX statements to subject/product for chain of custody graph. Dependencies: EXCITITOR-ATTEST-73-001. | Excititor Core Guild (src/Excititor/__Libraries/StellaOps.Excititor.Core/TASKS.md)
|
||||||
EXCITITOR-CONN-MS-01-003 – Trust metadata & provenance hints | Team Excititor Connectors – MSRC | TODO – Emit cosign/AAD issuer metadata, attach provenance details, and document policy integration. | EXCITITOR-CONN-MS-01-002, EXCITITOR-POLICY-01-001 (src/Excititor/__Libraries/StellaOps.Excititor.Connectors.MSRC.CSAF/TASKS.md)
|
EXCITITOR-CONN-MS-01-003 – Trust metadata & provenance hints | Team Excititor Connectors – MSRC | TODO – Emit cosign/AAD issuer metadata, attach provenance details, and document policy integration. | EXCITITOR-CONN-MS-01-002, EXCITITOR-POLICY-01-001 (src/Excititor/__Libraries/StellaOps.Excititor.Connectors.MSRC.CSAF/TASKS.md)
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ Summary: Scanner & Surface focus on Scanner (phase VII).
|
|||||||
Task ID | State | Task description | Owners (Source)
|
Task ID | State | Task description | Owners (Source)
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
SCANNER-ENTRYTRACE-18-504 | TODO | Emit EntryTrace AOC NDJSON (`entrytrace.entry/node/edge/target/warning/capability`) and wire CLI/service streaming outputs. Dependencies: SCANNER-ENTRYTRACE-18-503. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md)
|
SCANNER-ENTRYTRACE-18-504 | TODO | Emit EntryTrace AOC NDJSON (`entrytrace.entry/node/edge/target/warning/capability`) and wire CLI/service streaming outputs. Dependencies: SCANNER-ENTRYTRACE-18-503. | EntryTrace Guild (src/Scanner/__Libraries/StellaOps.Scanner.EntryTrace/TASKS.md)
|
||||||
SCANNER-ENV-01 | DOING (2025-11-02) | Replace ad-hoc environment reads with `StellaOps.Scanner.Surface.Env` helpers for cache roots and CAS endpoints.<br>2025-11-02: Env helper wiring drafted for Worker startup; initial tests validate cache root resolution.<br>2025-11-05 14:55Z: Continuing integration by propagating resolved settings into cache/secret services and prepping worker smoke tests + docs updates.<br>2025-11-05 19:18Z: Bound `SurfaceCacheOptions` root to Surface.Env settings and added configurator unit coverage.<br>2025-11-06 17:05Z: Documented misconfiguration warnings and updated module README to highlight Surface.Env usage. | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md)
|
SCANNER-ENV-01 | TODO (2025-11-06) | Replace ad-hoc environment reads with `StellaOps.Scanner.Surface.Env` helpers for cache roots and CAS endpoints.<br>2025-11-02: Env helper wiring drafted for Worker startup; initial tests validate cache root resolution.<br>2025-11-05 14:55Z: Continuing integration by propagating resolved settings into cache/secret services and prepping worker smoke tests + docs updates.<br>2025-11-05 19:18Z: Bound `SurfaceCacheOptions` root to Surface.Env settings and added configurator unit coverage.<br>2025-11-06 17:05Z: Documented misconfiguration warnings and updated module README to highlight Surface.Env usage.<br>2025-11-06 07:45Z: Helm/Compose env profiles (dev/stage/prod/airgap/mirror) now emit `SCANNER_SURFACE_*` defaults and ops README covers rollout warnings.<br>2025-11-06 07:55Z: Paused pending automation tracked under `DEVOPS-OPENSSL-11-001/002` and additional Surface.Env fixtures. | Scanner Worker Guild (src/Scanner/StellaOps.Scanner.Worker/TASKS.md)
|
||||||
SCANNER-ENV-02 | DOING (2025-11-02) | Wire Surface.Env helpers into WebService hosting (cache roots, feature flags) and document configuration. Dependencies: SCANNER-ENV-01.<br>2025-11-02: WebService bootstrap now consumes Surface.Env helpers for cache roots and feature flag toggles; configuration doc draft pending.<br>2025-11-05 14:55Z: Picking up configuration/documentation work and aligning API readiness checks with Surface.Env validation outputs.<br>2025-11-05 19:18Z: Added unit test for Surface.Env cache root binding and ensured configurator registration.<br>2025-11-06 17:05Z: Surface.Env design doc expanded with warning catalogue and release notes, README refreshed. | Scanner WebService Guild, Ops Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
|
SCANNER-ENV-02 | TODO (2025-11-06) | Wire Surface.Env helpers into WebService hosting (cache roots, feature flags) and document configuration. Dependencies: SCANNER-ENV-01.<br>2025-11-02: WebService bootstrap now consumes Surface.Env helpers for cache roots and feature flag toggles; configuration doc draft pending.<br>2025-11-05 14:55Z: Picking up configuration/documentation work and aligning API readiness checks with Surface.Env validation outputs.<br>2025-11-05 19:18Z: Added unit test for Surface.Env cache root binding and ensured configurator registration.<br>2025-11-06 17:05Z: Surface.Env design doc expanded with warning catalogue and release notes, README refreshed.<br>2025-11-06 07:45Z: Helm/Compose templates ship `SCANNER_SURFACE_*` defaults across dev/stage/prod/airgap/mirror profiles with rollout guidance in deploy docs.<br>2025-11-06 07:55Z: Paused; follow-up automation tracked under `DEVOPS-OPENSSL-11-001/002` and readiness tests outstanding. | Scanner WebService Guild, Ops Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
|
||||||
SCANNER-ENV-03 | TODO | Adopt Surface.Env helpers for plugin configuration (cache roots, CAS endpoints, feature toggles). Dependencies: SCANNER-ENV-02. | BuildX Plugin Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md)
|
SCANNER-ENV-03 | TODO | Adopt Surface.Env helpers for plugin configuration (cache roots, CAS endpoints, feature toggles). Dependencies: SCANNER-ENV-02. | BuildX Plugin Guild (src/Scanner/StellaOps.Scanner.Sbomer.BuildXPlugin/TASKS.md)
|
||||||
SCANNER-EVENTS-16-301 | BLOCKED (2025-10-26) | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
|
SCANNER-EVENTS-16-301 | BLOCKED (2025-10-26) | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
|
||||||
SCANNER-EVENTS-16-302 | DOING (2025-10-26) | Extend orchestrator event links (report/policy/attestation) once endpoints are finalised across gateway + console. Dependencies: SCANNER-EVENTS-16-301. | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
|
SCANNER-EVENTS-16-302 | DOING (2025-10-26) | Extend orchestrator event links (report/policy/attestation) once endpoints are finalised across gateway + console. Dependencies: SCANNER-EVENTS-16-301. | Scanner WebService Guild (src/Scanner/StellaOps.Scanner.WebService/TASKS.md)
|
||||||
|
|||||||
BIN
local-nuget/Google.Api.Gax.Grpc.4.7.0.nupkg
Normal file
BIN
local-nuget/Google.Api.Gax.Grpc.4.7.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Google.Apis.Core.1.64.0.nupkg
Normal file
BIN
local-nuget/Google.Apis.Core.1.64.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Google.Cloud.Kms.V1.3.19.0.nupkg
Normal file
BIN
local-nuget/Google.Cloud.Kms.V1.3.19.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Google.Protobuf.3.31.1.nupkg
Normal file
BIN
local-nuget/Google.Protobuf.3.31.1.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Grpc.Auth.2.71.0.nupkg
Normal file
BIN
local-nuget/Grpc.Auth.2.71.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Grpc.Core.Api.2.71.0.nupkg
Normal file
BIN
local-nuget/Grpc.Core.Api.2.71.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Grpc.Net.Client.2.71.0.nupkg
Normal file
BIN
local-nuget/Grpc.Net.Client.2.71.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Grpc.Net.Common.2.71.0.nupkg
Normal file
BIN
local-nuget/Grpc.Net.Common.2.71.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Grpc.Tools.2.71.0.nupkg
Normal file
BIN
local-nuget/Grpc.Tools.2.71.0.nupkg
Normal file
Binary file not shown.
BIN
local-nuget/Pkcs11Interop.5.3.0.nupkg
Normal file
BIN
local-nuget/Pkcs11Interop.5.3.0.nupkg
Normal file
Binary file not shown.
@@ -13,6 +13,9 @@
|
|||||||
> 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.
|
> 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. |
|
| 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).
|
> 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-OPENSSL-11-001 | TODO (2025-11-06) | DevOps Guild, Build Infra Guild | — | Package the OpenSSL 1.1 shim (`tests/native/openssl-1.1/linux-x64`) into test harness output so Mongo2Go suites discover it automatically. | Shim copied during `dotnet test`, documentation updated, redundant manual extraction removed. |
|
||||||
|
> 2025-11-06: Interim guidance published in `tests/native/openssl-1.1/README.md` and `deploy/README.md`; automation still required.
|
||||||
|
| DEVOPS-OPENSSL-11-002 | TODO (2025-11-06) | DevOps Guild, CI Guild | DEVOPS-OPENSSL-11-001 | Ensure CI runners and Docker images that execute Mongo2Go tests export `LD_LIBRARY_PATH` (or embed the shim) to unblock unattended pipelines. | CI jobs set the variable or bake the libraries; runbook documents the location; smoke builds green without manual exports. |
|
||||||
| 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. |
|
| 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).
|
> 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-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. |
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ using StellaOps.Excititor.Policy;
|
|||||||
using StellaOps.Excititor.Storage.Mongo;
|
using StellaOps.Excititor.Storage.Mongo;
|
||||||
using StellaOps.Excititor.WebService.Endpoints;
|
using StellaOps.Excititor.WebService.Endpoints;
|
||||||
using StellaOps.Excititor.WebService.Services;
|
using StellaOps.Excititor.WebService.Services;
|
||||||
using StellaOps.Excititor.Core;
|
|
||||||
using StellaOps.Excititor.Core.Aoc;
|
using StellaOps.Excititor.Core.Aoc;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ If you are working on this file you need to read docs/modules/excititor/ARCHITEC
|
|||||||
# TASKS
|
# TASKS
|
||||||
| Task | Owner(s) | Depends on | Notes |
|
| Task | Owner(s) | Depends on | Notes |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
|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.<br>2025-10-31: Verifier now tolerates duplicate source providers from AOC raw projections, downgrades offline Rekor verification to a degraded result, and enforces trusted signer registry checks with detailed diagnostics/tests.<br>2025-11-05 14:35Z: Picking up diagnostics record/ActivitySource work and aligning metrics dimensions before wiring verifier into WebService/Worker paths.|
|
|EXCITITOR-ATTEST-01-003 – Verification suite & observability|Team Excititor Attestation|EXCITITOR-ATTEST-01-002|TODO (2025-11-06) – 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.<br>2025-10-31: Verifier now tolerates duplicate source providers from AOC raw projections, downgrades offline Rekor verification to a degraded result, and enforces trusted signer registry checks with detailed diagnostics/tests.<br>2025-11-05 14:35Z: Picking up diagnostics record/ActivitySource work and aligning metrics dimensions before wiring verifier into WebService/Worker paths.|
|
||||||
> 2025-11-05 19:10Z: Worker signature verifier now emits structured diagnostics/metrics via `VexAttestationDiagnostics`; attestation verification results flow into metric labels and logs.
|
> 2025-11-05 19:10Z: Worker signature verifier now emits structured diagnostics/metrics via `VexAttestationDiagnostics`; attestation verification results flow into metric labels and logs.
|
||||||
|
> 2025-11-06 07:12Z: Export verifier builds unblocked; Excititor worker + web service test suites pass with diagnostics wiring (`dotnet test` invocations succeed with staged libssl1.1).
|
||||||
|
> 2025-11-06 07:55Z: Paused after documenting OpenSSL shim usage; follow-up automation tracked under `DEVOPS-OPENSSL-11-001/002`.
|
||||||
> Remark (2025-10-22): Added verifier implementation + metrics/tests; next steps include wiring into WebService/Worker flows and expanding negative-path coverage.
|
> Remark (2025-10-22): Added verifier implementation + metrics/tests; next steps include wiring into WebService/Worker flows and expanding negative-path coverage.
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ public sealed class VexExportEngine : IExportEngine
|
|||||||
cached.PolicyDigest,
|
cached.PolicyDigest,
|
||||||
cached.ConsensusDigest,
|
cached.ConsensusDigest,
|
||||||
cached.ScoreDigest,
|
cached.ScoreDigest,
|
||||||
|
cached.QuietProvenance,
|
||||||
cached.Attestation,
|
cached.Attestation,
|
||||||
cached.SizeBytes);
|
cached.SizeBytes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ internal static class VexExportEnvelopeBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed record VexExportEnvelopeContext(
|
public sealed record VexExportEnvelopeContext(
|
||||||
ImmutableArray<VexConsensus> Consensus,
|
ImmutableArray<VexConsensus> Consensus,
|
||||||
string ConsensusCanonicalJson,
|
string ConsensusCanonicalJson,
|
||||||
VexContentAddress ConsensusDigest,
|
VexContentAddress ConsensusDigest,
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ public sealed class VexMirrorBundlePublisher : IVexMirrorBundlePublisher
|
|||||||
ToRelativePath(mirrorRoot, manifestPath),
|
ToRelativePath(mirrorRoot, manifestPath),
|
||||||
manifestBytes.LongLength,
|
manifestBytes.LongLength,
|
||||||
ComputeDigest(manifestBytes),
|
ComputeDigest(manifestBytes),
|
||||||
signature: null);
|
Signature: null);
|
||||||
|
|
||||||
var bundleDescriptor = manifestDocument.Bundle with
|
var bundleDescriptor = manifestDocument.Bundle with
|
||||||
{
|
{
|
||||||
@@ -298,7 +298,7 @@ public sealed class VexMirrorBundlePublisher : IVexMirrorBundlePublisher
|
|||||||
manifestDocument.DomainId,
|
manifestDocument.DomainId,
|
||||||
manifestDocument.DisplayName,
|
manifestDocument.DisplayName,
|
||||||
manifestDocument.GeneratedAt,
|
manifestDocument.GeneratedAt,
|
||||||
manifestDocument.Exports.Length,
|
manifestDocument.Exports.Count,
|
||||||
manifestDescriptor,
|
manifestDescriptor,
|
||||||
bundleDescriptor,
|
bundleDescriptor,
|
||||||
exportKeys));
|
exportKeys));
|
||||||
@@ -474,6 +474,11 @@ public sealed class VexMirrorBundlePublisher : IVexMirrorBundlePublisher
|
|||||||
|
|
||||||
private JsonMirrorSigningContext PrepareSigningContext(MirrorSigningOptions signingOptions)
|
private JsonMirrorSigningContext PrepareSigningContext(MirrorSigningOptions signingOptions)
|
||||||
{
|
{
|
||||||
|
if (_cryptoRegistry is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Mirror signing requires a crypto provider registry to be configured.");
|
||||||
|
}
|
||||||
|
|
||||||
var algorithm = string.IsNullOrWhiteSpace(signingOptions.Algorithm)
|
var algorithm = string.IsNullOrWhiteSpace(signingOptions.Algorithm)
|
||||||
? SignatureAlgorithms.Es256
|
? SignatureAlgorithms.Es256
|
||||||
: signingOptions.Algorithm.Trim();
|
: signingOptions.Algorithm.Trim();
|
||||||
@@ -496,7 +501,7 @@ public sealed class VexMirrorBundlePublisher : IVexMirrorBundlePublisher
|
|||||||
var provider = ResolveProvider(algorithm, providerHint);
|
var provider = ResolveProvider(algorithm, providerHint);
|
||||||
var signingKey = LoadSigningKey(signingOptions, provider, algorithm);
|
var signingKey = LoadSigningKey(signingOptions, provider, algorithm);
|
||||||
provider.UpsertSigningKey(signingKey);
|
provider.UpsertSigningKey(signingKey);
|
||||||
resolved = _cryptoRegistry.ResolveSigner(CryptoCapability.Signing, algorithm, new CryptoKeyReference(keyId, provider.Name), provider.Name);
|
resolved = _cryptoRegistry!.ResolveSigner(CryptoCapability.Signing, algorithm, new CryptoKeyReference(keyId, provider.Name), provider.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JsonMirrorSigningContext(resolved.Signer, algorithm, resolved.ProviderName, _timeProvider);
|
return new JsonMirrorSigningContext(resolved.Signer, algorithm, resolved.ProviderName, _timeProvider);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|----|--------|----------|------------|-------------|---------------|
|
|----|--------|----------|------------|-------------|---------------|
|
||||||
| SCAN-REPLAY-186-001 | TODO | Scanner WebService Guild | REPLAY-CORE-185-001 | Implement scan `record` mode producing replay manifests/bundles, capture policy/feed/tool hashes, and update `docs/modules/scanner/architecture.md` referencing `docs/replay/DETERMINISTIC_REPLAY.md` Section 6. | API/worker integration tests cover record mode; docs merged; replay artifacts stored per spec. |
|
| SCAN-REPLAY-186-001 | TODO | Scanner WebService Guild | REPLAY-CORE-185-001 | Implement scan `record` mode producing replay manifests/bundles, capture policy/feed/tool hashes, and update `docs/modules/scanner/architecture.md` referencing `docs/replay/DETERMINISTIC_REPLAY.md` Section 6. | API/worker integration tests cover record mode; docs merged; replay artifacts stored per spec. |
|
||||||
| SCANNER-SURFACE-02 | DONE (2025-11-05) | Scanner WebService Guild | SURFACE-FS-02 | Publish Surface.FS pointers (CAS URIs, manifests) via scan/report APIs and update attestation metadata.<br>2025-11-05: Surface pointers projected through scan/report endpoints, orchestrator samples + DSSE fixtures refreshed with manifest block, readiness tests updated to use validator stub. | OpenAPI updated; clients regenerated; integration tests validate pointer presence and tenancy. |
|
| SCANNER-SURFACE-02 | DONE (2025-11-05) | Scanner WebService Guild | SURFACE-FS-02 | Publish Surface.FS pointers (CAS URIs, manifests) via scan/report APIs and update attestation metadata.<br>2025-11-05: Surface pointers projected through scan/report endpoints, orchestrator samples + DSSE fixtures refreshed with manifest block, readiness tests updated to use validator stub. | OpenAPI updated; clients regenerated; integration tests validate pointer presence and tenancy. |
|
||||||
| SCANNER-ENV-02 | DOING (2025-11-02) | Scanner WebService Guild, Ops Guild | SURFACE-ENV-02 | Wire Surface.Env helpers into WebService hosting (cache roots, feature flags) and document configuration.<br>2025-11-02: Cache root resolution switched to helper; feature flag bindings updated; Helm/Compose updates pending review.<br>2025-11-05 14:55Z: Aligning readiness checks, docs, and Helm/Compose templates with Surface.Env outputs and planning test coverage for configuration fallbacks.<br>2025-11-06 17:05Z: Surface.Env documentation/README refreshed; warning catalogue captured for ops handoff. | Service uses helper; env table documented; helm/compose templates updated. |
|
| SCANNER-ENV-02 | TODO (2025-11-06) | Scanner WebService Guild, Ops Guild | SURFACE-ENV-02 | Wire Surface.Env helpers into WebService hosting (cache roots, feature flags) and document configuration.<br>2025-11-02: Cache root resolution switched to helper; feature flag bindings updated; Helm/Compose updates pending review.<br>2025-11-05 14:55Z: Aligning readiness checks, docs, and Helm/Compose templates with Surface.Env outputs and planning test coverage for configuration fallbacks.<br>2025-11-06 17:05Z: Surface.Env documentation/README refreshed; warning catalogue captured for ops handoff.<br>2025-11-06 07:45Z: Helm values (dev/stage/prod/airgap/mirror) and Compose examples updated with `SCANNER_SURFACE_*` defaults plus rollout warning note in `deploy/README.md`.<br>2025-11-06 07:55Z: Paused; follow-up automation captured under `DEVOPS-OPENSSL-11-001/002` and pending Surface.Env readiness tests. | Service uses helper; env table documented; helm/compose templates updated. |
|
||||||
> 2025-11-05 19:18Z: Added configurator to project wiring and unit test ensuring Surface.Env cache root is honoured.
|
> 2025-11-05 19:18Z: Added configurator to project wiring and unit test ensuring Surface.Env cache root is honoured.
|
||||||
| SCANNER-SECRETS-02 | DOING (2025-11-02) | Scanner WebService Guild, Security Guild | SURFACE-SECRETS-02 | Replace ad-hoc secret wiring with Surface.Secrets for report/export operations (registry and CAS tokens).<br>2025-11-02: Export/report flows now depend on Surface.Secrets stub; integration tests in progress. | Secrets fetched through shared provider; unit/integration tests cover rotation + failure cases. |
|
| SCANNER-SECRETS-02 | DOING (2025-11-02) | Scanner WebService Guild, Security Guild | SURFACE-SECRETS-02 | Replace ad-hoc secret wiring with Surface.Secrets for report/export operations (registry and CAS tokens).<br>2025-11-02: Export/report flows now depend on Surface.Secrets stub; integration tests in progress. | Secrets fetched through shared provider; unit/integration tests cover rotation + failure cases. |
|
||||||
| SCANNER-EVENTS-16-301 | BLOCKED (2025-10-26) | Scanner WebService Guild | ORCH-SVC-38-101, NOTIFY-SVC-38-001 | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Tests assert envelope schema + orchestrator publish; Notifier consumer harness passes; docs updated with new event contract. Blocked by .NET 10 preview OpenAPI/Auth dependency drift preventing `dotnet test` completion. |
|
| SCANNER-EVENTS-16-301 | BLOCKED (2025-10-26) | Scanner WebService Guild | ORCH-SVC-38-101, NOTIFY-SVC-38-001 | Emit orchestrator-compatible envelopes (`scanner.event.*`) and update integration tests to verify Notifier ingestion (no Redis queue coupling). | Tests assert envelope schema + orchestrator publish; Notifier consumer harness passes; docs updated with new event contract. Blocked by .NET 10 preview OpenAPI/Auth dependency drift preventing `dotnet test` completion. |
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
|----|--------|----------|------------|-------------|---------------|
|
|----|--------|----------|------------|-------------|---------------|
|
||||||
| SCAN-REPLAY-186-002 | TODO | Scanner Worker Guild | REPLAY-CORE-185-001 | Enforce deterministic analyzer execution when consuming replay input bundles, emit layer Merkle metadata, and author `docs/modules/scanner/deterministic-execution.md` summarising invariants from `docs/replay/DETERMINISTIC_REPLAY.md` Section 4. | Replay mode analyzers pass determinism tests; new doc merged; integration fixtures updated. |
|
| SCAN-REPLAY-186-002 | TODO | Scanner Worker Guild | REPLAY-CORE-185-001 | Enforce deterministic analyzer execution when consuming replay input bundles, emit layer Merkle metadata, and author `docs/modules/scanner/deterministic-execution.md` summarising invariants from `docs/replay/DETERMINISTIC_REPLAY.md` Section 4. | Replay mode analyzers pass determinism tests; new doc merged; integration fixtures updated. |
|
||||||
| SCANNER-SURFACE-01 | DOING (2025-11-02) | Scanner Worker Guild | SURFACE-FS-02 | Persist Surface.FS manifests after analyzer stages, including layer CAS metadata and EntryTrace fragments.<br>2025-11-02: Draft Surface.FS manifests emitted for sample scans; telemetry counters under review. | Integration tests prove cache entries exist; telemetry counters exported. |
|
| SCANNER-SURFACE-01 | DOING (2025-11-02) | Scanner Worker Guild | SURFACE-FS-02 | Persist Surface.FS manifests after analyzer stages, including layer CAS metadata and EntryTrace fragments.<br>2025-11-02: Draft Surface.FS manifests emitted for sample scans; telemetry counters under review. | Integration tests prove cache entries exist; telemetry counters exported. |
|
||||||
| SCANNER-ENV-01 | DOING (2025-11-02) | Scanner Worker Guild | SURFACE-ENV-02 | Replace ad-hoc environment reads with `StellaOps.Scanner.Surface.Env` helpers for cache roots and CAS endpoints.<br>2025-11-02: Worker bootstrap now resolves cache roots via helper; warning path documented; smoke tests running.<br>2025-11-05 14:55Z: Extending helper usage into cache/secrets configuration, updating worker validator wiring, and drafting docs/tests for new Surface.Env outputs.<br>2025-11-06 17:05Z: README/design docs updated with warning catalogue; startup logging guidance captured for ops runbooks. | Worker boots with helper; misconfiguration warnings documented; smoke tests updated. |
|
| SCANNER-ENV-01 | TODO (2025-11-06) | Scanner Worker Guild | SURFACE-ENV-02 | Replace ad-hoc environment reads with `StellaOps.Scanner.Surface.Env` helpers for cache roots and CAS endpoints.<br>2025-11-02: Worker bootstrap now resolves cache roots via helper; warning path documented; smoke tests running.<br>2025-11-05 14:55Z: Extending helper usage into cache/secrets configuration, updating worker validator wiring, and drafting docs/tests for new Surface.Env outputs.<br>2025-11-06 17:05Z: README/design docs updated with warning catalogue; startup logging guidance captured for ops runbooks.<br>2025-11-06 07:45Z: Helm/Compose env profiles (dev/stage/prod/airgap/mirror) now seed `SCANNER_SURFACE_*` defaults to keep worker cache roots aligned with Surface.Env helpers.<br>2025-11-06 07:55Z: Paused; pending automation tracked via `DEVOPS-OPENSSL-11-001/002` and Surface.Env test fixtures. | Worker boots with helper; misconfiguration warnings documented; smoke tests updated. |
|
||||||
> 2025-11-05 19:18Z: Bound `SurfaceCacheOptions` root directory to resolved Surface.Env settings and added unit coverage around the configurator.
|
> 2025-11-05 19:18Z: Bound `SurfaceCacheOptions` root directory to resolved Surface.Env settings and added unit coverage around the configurator.
|
||||||
| SCANNER-SECRETS-01 | DOING (2025-11-02) | Scanner Worker Guild, Security Guild | SURFACE-SECRETS-02 | Adopt `StellaOps.Scanner.Surface.Secrets` for registry/CAS credentials during scan execution.<br>2025-11-02: Surface.Secrets provider wired for CAS token retrieval; integration tests added. | Secrets fetched via shared provider; legacy secret code removed; integration tests cover rotation. |
|
| SCANNER-SECRETS-01 | DOING (2025-11-02) | Scanner Worker Guild, Security Guild | SURFACE-SECRETS-02 | Adopt `StellaOps.Scanner.Surface.Secrets` for registry/CAS credentials during scan execution.<br>2025-11-02: Surface.Secrets provider wired for CAS token retrieval; integration tests added. | Secrets fetched via shared provider; legacy secret code removed; integration tests cover rotation. |
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"schema": "scheduler-impact-index@1",
|
||||||
|
"generatedAt": "2025-10-01T00:00:00Z",
|
||||||
|
"image": {
|
||||||
|
"repository": "registry.stellaops.test/team/sample-service",
|
||||||
|
"digest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||||
|
"tag": "1.0.0"
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"purl": "pkg:docker/sample-service@1.0.0",
|
||||||
|
"usage": [
|
||||||
|
"runtime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purl": "pkg:pypi/requests@2.31.0",
|
||||||
|
"usage": [
|
||||||
|
"usedByEntrypoint"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
<ProjectReference Include="../StellaOps.Scheduler.Models/StellaOps.Scheduler.Models.csproj" />
|
<ProjectReference Include="../StellaOps.Scheduler.Models/StellaOps.Scheduler.Models.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Fixtures\**\*.json" />
|
||||||
<EmbeddedResource Include="..\..\samples\scanner\images\**\bom-index.json"
|
<EmbeddedResource Include="..\..\samples\scanner\images\**\bom-index.json"
|
||||||
Link="Fixtures\%(RecursiveDir)%(Filename)%(Extension)" />
|
Link="Fixtures\%(RecursiveDir)%(Filename)%(Extension)" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using StellaOps.Scheduler.ImpactIndex;
|
||||||
|
using StellaOps.Scheduler.Models;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace StellaOps.Scheduler.WebService.Tests;
|
||||||
|
|
||||||
|
public sealed class ImpactIndexFixtureTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void FixtureDirectoryExists()
|
||||||
|
{
|
||||||
|
var fixtureDirectory = GetFixtureDirectory();
|
||||||
|
Assert.True(Directory.Exists(fixtureDirectory), $"Fixture directory not found: {fixtureDirectory}");
|
||||||
|
|
||||||
|
var files = Directory.EnumerateFiles(fixtureDirectory, "bom-index.json", SearchOption.AllDirectories).ToArray();
|
||||||
|
Assert.NotEmpty(files);
|
||||||
|
|
||||||
|
var sampleFile = Path.Combine(fixtureDirectory, "sample", "bom-index.json");
|
||||||
|
Assert.Contains(sampleFile, files);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task FixtureImpactIndexLoadsSampleImage()
|
||||||
|
{
|
||||||
|
var fixtureDirectory = GetFixtureDirectory();
|
||||||
|
var options = new ImpactIndexStubOptions
|
||||||
|
{
|
||||||
|
FixtureDirectory = fixtureDirectory,
|
||||||
|
SnapshotId = "tests/impact-index-stub"
|
||||||
|
};
|
||||||
|
|
||||||
|
var index = new FixtureImpactIndex(options, TimeProvider.System, NullLogger<FixtureImpactIndex>.Instance);
|
||||||
|
var selector = new Selector(SelectorScope.AllImages);
|
||||||
|
|
||||||
|
var impactSet = await index.ResolveAllAsync(selector, usageOnly: false);
|
||||||
|
|
||||||
|
Assert.True(impactSet.Total > 0, "Expected the fixture impact index to load at least one image.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFixtureDirectory()
|
||||||
|
{
|
||||||
|
var assemblyLocation = typeof(SchedulerWebApplicationFactory).Assembly.Location;
|
||||||
|
var assemblyDirectory = Path.GetDirectoryName(assemblyLocation)
|
||||||
|
?? AppContext.BaseDirectory;
|
||||||
|
|
||||||
|
return Path.GetFullPath(Path.Combine(assemblyDirectory, "seed-data", "impact-index"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,16 +11,16 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using StellaOps.Scheduler.Models;
|
using StellaOps.Scheduler.Models;
|
||||||
using StellaOps.Scheduler.Queue;
|
using StellaOps.Scheduler.Queue;
|
||||||
using StellaOps.Scheduler.Storage.Mongo.Repositories;
|
using StellaOps.Scheduler.Storage.Mongo.Repositories;
|
||||||
|
|
||||||
namespace StellaOps.Scheduler.WebService.Tests;
|
namespace StellaOps.Scheduler.WebService.Tests;
|
||||||
|
|
||||||
public sealed class RunEndpointTests : IClassFixture<WebApplicationFactory<Program>>
|
public sealed class RunEndpointTests : IClassFixture<WebApplicationFactory<Program>>
|
||||||
{
|
{
|
||||||
private readonly WebApplicationFactory<Program> _factory;
|
private readonly WebApplicationFactory<Program> _factory;
|
||||||
|
|
||||||
public RunEndpointTests(WebApplicationFactory<Program> factory)
|
public RunEndpointTests(WebApplicationFactory<Program> factory)
|
||||||
{
|
{
|
||||||
_factory = factory;
|
_factory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -100,13 +100,13 @@ public sealed class RunEndpointTests : IClassFixture<WebApplicationFactory<Progr
|
|||||||
var scheduleId = scheduleJson.GetProperty("schedule").GetProperty("id").GetString();
|
var scheduleId = scheduleJson.GetProperty("schedule").GetProperty("id").GetString();
|
||||||
Assert.False(string.IsNullOrEmpty(scheduleId));
|
Assert.False(string.IsNullOrEmpty(scheduleId));
|
||||||
|
|
||||||
var previewResponse = await client.PostAsJsonAsync("/api/v1/scheduler/runs/preview", new
|
var previewResponse = await client.PostAsJsonAsync("/api/v1/scheduler/runs/preview", new
|
||||||
{
|
{
|
||||||
scheduleId,
|
scheduleId,
|
||||||
usageOnly = true,
|
usageOnly = true,
|
||||||
sampleSize = 3
|
sampleSize = 3
|
||||||
});
|
});
|
||||||
|
|
||||||
previewResponse.EnsureSuccessStatusCode();
|
previewResponse.EnsureSuccessStatusCode();
|
||||||
var preview = await previewResponse.Content.ReadFromJsonAsync<JsonElement>();
|
var preview = await previewResponse.Content.ReadFromJsonAsync<JsonElement>();
|
||||||
Assert.True(preview.GetProperty("total").GetInt32() >= 0);
|
Assert.True(preview.GetProperty("total").GetInt32() >= 0);
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc.Testing;
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||||
using StellaOps.Scheduler.WebService.Options;
|
using StellaOps.Scheduler.WebService.Options;
|
||||||
using StellaOps.Scheduler.WebService.Runs;
|
using StellaOps.Scheduler.WebService.Runs;
|
||||||
|
using StellaOps.Scheduler.ImpactIndex;
|
||||||
|
|
||||||
namespace StellaOps.Scheduler.WebService.Tests;
|
namespace StellaOps.Scheduler.WebService.Tests;
|
||||||
|
|
||||||
@@ -15,6 +18,8 @@ public sealed class SchedulerWebApplicationFactory : WebApplicationFactory<Progr
|
|||||||
{
|
{
|
||||||
builder.ConfigureAppConfiguration((_, configuration) =>
|
builder.ConfigureAppConfiguration((_, configuration) =>
|
||||||
{
|
{
|
||||||
|
var fixtureDirectory = GetFixtureDirectory();
|
||||||
|
|
||||||
configuration.AddInMemoryCollection(new[]
|
configuration.AddInMemoryCollection(new[]
|
||||||
{
|
{
|
||||||
new KeyValuePair<string, string?>("Scheduler:Authority:Enabled", "false"),
|
new KeyValuePair<string, string?>("Scheduler:Authority:Enabled", "false"),
|
||||||
@@ -27,12 +32,22 @@ public sealed class SchedulerWebApplicationFactory : WebApplicationFactory<Progr
|
|||||||
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:Enabled", "true"),
|
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:Enabled", "true"),
|
||||||
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:HmacSecret", "excitor-secret"),
|
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:HmacSecret", "excitor-secret"),
|
||||||
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:RateLimitRequests", "20"),
|
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:RateLimitRequests", "20"),
|
||||||
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:RateLimitWindowSeconds", "60")
|
new KeyValuePair<string, string?>("Scheduler:Events:Webhooks:Excitor:RateLimitWindowSeconds", "60"),
|
||||||
|
new KeyValuePair<string, string?>("Scheduler:ImpactIndex:FixtureDirectory", fixtureDirectory)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
builder.ConfigureServices(services =>
|
builder.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
|
var fixtureDirectory = GetFixtureDirectory();
|
||||||
|
|
||||||
|
services.RemoveAll<ImpactIndexStubOptions>();
|
||||||
|
services.AddSingleton(new ImpactIndexStubOptions
|
||||||
|
{
|
||||||
|
FixtureDirectory = fixtureDirectory,
|
||||||
|
SnapshotId = "tests/impact-index-stub"
|
||||||
|
});
|
||||||
|
|
||||||
services.Configure<SchedulerEventsOptions>(options =>
|
services.Configure<SchedulerEventsOptions>(options =>
|
||||||
{
|
{
|
||||||
options.Webhooks ??= new SchedulerInboundWebhooksOptions();
|
options.Webhooks ??= new SchedulerInboundWebhooksOptions();
|
||||||
@@ -52,4 +67,14 @@ public sealed class SchedulerWebApplicationFactory : WebApplicationFactory<Progr
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetFixtureDirectory()
|
||||||
|
{
|
||||||
|
var assemblyLocation = typeof(SchedulerWebApplicationFactory).Assembly.Location;
|
||||||
|
var assemblyDirectory = Path.GetDirectoryName(assemblyLocation)
|
||||||
|
?? AppContext.BaseDirectory;
|
||||||
|
|
||||||
|
var fixtureDirectory = Path.Combine(assemblyDirectory, "seed-data", "impact-index");
|
||||||
|
return Path.GetFullPath(fixtureDirectory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,4 +18,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="../../StellaOps.Scheduler.WebService/StellaOps.Scheduler.WebService.csproj" />
|
<ProjectReference Include="../../StellaOps.Scheduler.WebService/StellaOps.Scheduler.WebService.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="seed-data/impact-index/**">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"schema": "scheduler-impact-index@1",
|
||||||
|
"generatedAt": "2025-10-01T00:00:00Z",
|
||||||
|
"image": {
|
||||||
|
"repository": "registry.stellaops.test/team/sample-service",
|
||||||
|
"digest": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
||||||
|
"tag": "1.0.0"
|
||||||
|
},
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"purl": "pkg:docker/sample-service@1.0.0",
|
||||||
|
"usage": [
|
||||||
|
"runtime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"purl": "pkg:pypi/requests@2.31.0",
|
||||||
|
"usage": [
|
||||||
|
"usedByEntrypoint"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using StellaOps.TaskRunner.Core.Execution;
|
||||||
|
using StellaOps.TaskRunner.Core.Planning;
|
||||||
|
|
||||||
|
namespace StellaOps.TaskRunner.Infrastructure.Execution;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stores pack run artifacts on the local file system so they can be mirrored to the eventual remote store.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class FilesystemPackRunArtifactUploader : IPackRunArtifactUploader
|
||||||
|
{
|
||||||
|
private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
|
||||||
|
{
|
||||||
|
WriteIndented = true
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly string rootPath;
|
||||||
|
private readonly ILogger<FilesystemPackRunArtifactUploader> logger;
|
||||||
|
private readonly TimeProvider timeProvider;
|
||||||
|
|
||||||
|
public FilesystemPackRunArtifactUploader(
|
||||||
|
string rootPath,
|
||||||
|
TimeProvider? timeProvider,
|
||||||
|
ILogger<FilesystemPackRunArtifactUploader> logger)
|
||||||
|
{
|
||||||
|
ArgumentException.ThrowIfNullOrWhiteSpace(rootPath);
|
||||||
|
|
||||||
|
this.rootPath = Path.GetFullPath(rootPath);
|
||||||
|
this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||||
|
this.timeProvider = timeProvider ?? TimeProvider.System;
|
||||||
|
|
||||||
|
Directory.CreateDirectory(this.rootPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UploadAsync(
|
||||||
|
PackRunExecutionContext context,
|
||||||
|
PackRunState state,
|
||||||
|
IReadOnlyList<TaskPackPlanOutput> outputs,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
ArgumentNullException.ThrowIfNull(context);
|
||||||
|
ArgumentNullException.ThrowIfNull(state);
|
||||||
|
ArgumentNullException.ThrowIfNull(outputs);
|
||||||
|
|
||||||
|
if (outputs.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var destinationRoot = Path.Combine(rootPath, SanitizeFileName(context.RunId));
|
||||||
|
var filesRoot = Path.Combine(destinationRoot, "files");
|
||||||
|
var expressionsRoot = Path.Combine(destinationRoot, "expressions");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(destinationRoot);
|
||||||
|
|
||||||
|
var manifest = new ArtifactManifest(
|
||||||
|
context.RunId,
|
||||||
|
timeProvider.GetUtcNow(),
|
||||||
|
new List<ArtifactRecord>(outputs.Count));
|
||||||
|
|
||||||
|
foreach (var output in outputs)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var record = await ProcessOutputAsync(
|
||||||
|
context,
|
||||||
|
output,
|
||||||
|
destinationRoot,
|
||||||
|
filesRoot,
|
||||||
|
expressionsRoot,
|
||||||
|
cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
manifest.Outputs.Add(record);
|
||||||
|
}
|
||||||
|
|
||||||
|
var manifestPath = Path.Combine(destinationRoot, "artifact-manifest.json");
|
||||||
|
await using (var stream = File.Open(manifestPath, FileMode.Create, FileAccess.Write, FileShare.None))
|
||||||
|
{
|
||||||
|
await JsonSerializer.SerializeAsync(stream, manifest, SerializerOptions, cancellationToken)
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation(
|
||||||
|
"Pack run {RunId} artifact manifest written to {Path} with {Count} output entries.",
|
||||||
|
context.RunId,
|
||||||
|
manifestPath,
|
||||||
|
manifest.Outputs.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<ArtifactRecord> ProcessOutputAsync(
|
||||||
|
PackRunExecutionContext context,
|
||||||
|
TaskPackPlanOutput output,
|
||||||
|
string destinationRoot,
|
||||||
|
string filesRoot,
|
||||||
|
string expressionsRoot,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var sourcePath = ResolveString(output.Path);
|
||||||
|
var expressionNode = ResolveExpression(output.Expression);
|
||||||
|
var status = "skipped";
|
||||||
|
string? storedPath = null;
|
||||||
|
string? notes = null;
|
||||||
|
|
||||||
|
if (IsFileOutput(output))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(sourcePath))
|
||||||
|
{
|
||||||
|
status = "unresolved";
|
||||||
|
notes = "Output path requires runtime value.";
|
||||||
|
}
|
||||||
|
else if (!File.Exists(sourcePath))
|
||||||
|
{
|
||||||
|
status = "missing";
|
||||||
|
notes = $"Source file '{sourcePath}' not found.";
|
||||||
|
logger.LogWarning(
|
||||||
|
"Pack run {RunId} output {Output} referenced missing file {Path}.",
|
||||||
|
context.RunId,
|
||||||
|
output.Name,
|
||||||
|
sourcePath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(filesRoot);
|
||||||
|
|
||||||
|
var destinationPath = Path.Combine(filesRoot, DetermineDestinationFileName(output, sourcePath));
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)!);
|
||||||
|
|
||||||
|
await CopyFileAsync(sourcePath, destinationPath, cancellationToken).ConfigureAwait(false);
|
||||||
|
storedPath = GetRelativePath(destinationPath, destinationRoot);
|
||||||
|
status = "copied";
|
||||||
|
|
||||||
|
logger.LogInformation(
|
||||||
|
"Pack run {RunId} output {Output} copied to {Destination}.",
|
||||||
|
context.RunId,
|
||||||
|
output.Name,
|
||||||
|
destinationPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expressionNode is not null)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(expressionsRoot);
|
||||||
|
|
||||||
|
var expressionPath = Path.Combine(
|
||||||
|
expressionsRoot,
|
||||||
|
$"{SanitizeFileName(output.Name)}.json");
|
||||||
|
|
||||||
|
var json = expressionNode.ToJsonString(SerializerOptions);
|
||||||
|
await File.WriteAllTextAsync(expressionPath, json, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
storedPath ??= GetRelativePath(expressionPath, destinationRoot);
|
||||||
|
status = status == "copied" ? "copied" : "materialized";
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ArtifactRecord(
|
||||||
|
output.Name,
|
||||||
|
output.Type,
|
||||||
|
sourcePath,
|
||||||
|
storedPath,
|
||||||
|
status,
|
||||||
|
notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task CopyFileAsync(string sourcePath, string destinationPath, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await using var source = File.Open(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
await using var destination = File.Open(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||||
|
await source.CopyToAsync(destination, cancellationToken).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsFileOutput(TaskPackPlanOutput output)
|
||||||
|
=> string.Equals(output.Type, "file", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
private static string DetermineDestinationFileName(TaskPackPlanOutput output, string sourcePath)
|
||||||
|
{
|
||||||
|
var extension = Path.GetExtension(sourcePath);
|
||||||
|
var baseName = SanitizeFileName(output.Name);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(extension) &&
|
||||||
|
!baseName.EndsWith(extension, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return baseName + extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string? ResolveString(TaskPackPlanParameterValue? parameter)
|
||||||
|
{
|
||||||
|
if (parameter is null || parameter.RequiresRuntimeValue || parameter.Value is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parameter.Value is JsonValue jsonValue && jsonValue.TryGetValue<string>(out var value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonNode? ResolveExpression(TaskPackPlanParameterValue? parameter)
|
||||||
|
{
|
||||||
|
if (parameter is null || parameter.RequiresRuntimeValue)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameter.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string SanitizeFileName(string value)
|
||||||
|
{
|
||||||
|
var result = value;
|
||||||
|
foreach (var invalid in Path.GetInvalidFileNameChars())
|
||||||
|
{
|
||||||
|
result = result.Replace(invalid, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.IsNullOrWhiteSpace(result) ? "output" : result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetRelativePath(string path, string root)
|
||||||
|
=> Path.GetRelativePath(root, path)
|
||||||
|
.Replace('\\', '/');
|
||||||
|
|
||||||
|
private sealed record ArtifactManifest(string RunId, DateTimeOffset UploadedAt, List<ArtifactRecord> Outputs);
|
||||||
|
|
||||||
|
private sealed record ArtifactRecord(
|
||||||
|
string Name,
|
||||||
|
string Type,
|
||||||
|
string? SourcePath,
|
||||||
|
string? StoredPath,
|
||||||
|
string Status,
|
||||||
|
string? Notes);
|
||||||
|
}
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Nodes;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
using StellaOps.TaskRunner.Core.Execution;
|
||||||
|
using StellaOps.TaskRunner.Core.Planning;
|
||||||
|
using StellaOps.TaskRunner.Infrastructure.Execution;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace StellaOps.TaskRunner.Tests;
|
||||||
|
|
||||||
|
public sealed class FilesystemPackRunArtifactUploaderTests : IDisposable
|
||||||
|
{
|
||||||
|
private readonly string artifactsRoot;
|
||||||
|
|
||||||
|
public FilesystemPackRunArtifactUploaderTests()
|
||||||
|
{
|
||||||
|
artifactsRoot = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task CopiesFileOutputs()
|
||||||
|
{
|
||||||
|
var sourceFile = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():n}.txt");
|
||||||
|
await File.WriteAllTextAsync(sourceFile, "artifact-content", TestContext.Current.CancellationToken);
|
||||||
|
|
||||||
|
var uploader = CreateUploader();
|
||||||
|
var output = CreateFileOutput("bundle", sourceFile);
|
||||||
|
var context = CreateContext();
|
||||||
|
var state = CreateState(context);
|
||||||
|
|
||||||
|
await uploader.UploadAsync(context, state, new[] { output }, TestContext.Current.CancellationToken);
|
||||||
|
|
||||||
|
var runPath = Path.Combine(artifactsRoot, context.RunId);
|
||||||
|
var filesDirectory = Path.Combine(runPath, "files");
|
||||||
|
var copiedFiles = Directory.GetFiles(filesDirectory);
|
||||||
|
Assert.Single(copiedFiles);
|
||||||
|
Assert.Equal("bundle.txt", Path.GetFileName(copiedFiles[0]));
|
||||||
|
Assert.Equal("artifact-content", await File.ReadAllTextAsync(copiedFiles[0], TestContext.Current.CancellationToken));
|
||||||
|
|
||||||
|
var manifest = await ReadManifestAsync(runPath);
|
||||||
|
Assert.Single(manifest.Outputs);
|
||||||
|
Assert.Equal("copied", manifest.Outputs[0].Status);
|
||||||
|
Assert.Equal("files/bundle.txt", manifest.Outputs[0].StoredPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RecordsMissingFilesWithoutThrowing()
|
||||||
|
{
|
||||||
|
var uploader = CreateUploader();
|
||||||
|
var output = CreateFileOutput("missing", Path.Combine(Path.GetTempPath(), "does-not-exist.txt"));
|
||||||
|
var context = CreateContext();
|
||||||
|
var state = CreateState(context);
|
||||||
|
|
||||||
|
await uploader.UploadAsync(context, state, new[] { output }, TestContext.Current.CancellationToken);
|
||||||
|
|
||||||
|
var manifest = await ReadManifestAsync(Path.Combine(artifactsRoot, context.RunId));
|
||||||
|
Assert.Equal("missing", manifest.Outputs[0].Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task WritesExpressionOutputsAsJson()
|
||||||
|
{
|
||||||
|
var uploader = CreateUploader();
|
||||||
|
var output = CreateExpressionOutput("metadata", JsonNode.Parse("""{"foo":"bar"}""")!);
|
||||||
|
var context = CreateContext();
|
||||||
|
var state = CreateState(context);
|
||||||
|
|
||||||
|
await uploader.UploadAsync(context, state, new[] { output }, TestContext.Current.CancellationToken);
|
||||||
|
|
||||||
|
var expressionPath = Path.Combine(artifactsRoot, context.RunId, "expressions", "metadata.json");
|
||||||
|
Assert.True(File.Exists(expressionPath));
|
||||||
|
|
||||||
|
var manifest = await ReadManifestAsync(Path.Combine(artifactsRoot, context.RunId));
|
||||||
|
Assert.Equal("materialized", manifest.Outputs[0].Status);
|
||||||
|
Assert.Equal("expressions/metadata.json", manifest.Outputs[0].StoredPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FilesystemPackRunArtifactUploader CreateUploader()
|
||||||
|
=> new(artifactsRoot, TimeProvider.System, NullLogger<FilesystemPackRunArtifactUploader>.Instance);
|
||||||
|
|
||||||
|
private static TaskPackPlanOutput CreateFileOutput(string name, string path)
|
||||||
|
=> new(
|
||||||
|
name,
|
||||||
|
Type: "file",
|
||||||
|
Path: new TaskPackPlanParameterValue(JsonValue.Create(path), null, null, false),
|
||||||
|
Expression: null);
|
||||||
|
|
||||||
|
private static TaskPackPlanOutput CreateExpressionOutput(string name, JsonNode expression)
|
||||||
|
=> new(
|
||||||
|
name,
|
||||||
|
Type: "object",
|
||||||
|
Path: null,
|
||||||
|
Expression: new TaskPackPlanParameterValue(expression, null, null, false));
|
||||||
|
|
||||||
|
private static PackRunExecutionContext CreateContext()
|
||||||
|
=> new("run-" + Guid.NewGuid().ToString("n"), CreatePlan(), DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
|
private static PackRunState CreateState(PackRunExecutionContext context)
|
||||||
|
=> PackRunState.Create(
|
||||||
|
runId: context.RunId,
|
||||||
|
planHash: context.Plan.Hash,
|
||||||
|
context.Plan,
|
||||||
|
failurePolicy: new TaskPackPlanFailurePolicy(1, 1, false),
|
||||||
|
requestedAt: DateTimeOffset.UtcNow,
|
||||||
|
steps: new Dictionary<string, PackRunStepStateRecord>(StringComparer.Ordinal),
|
||||||
|
timestamp: DateTimeOffset.UtcNow);
|
||||||
|
|
||||||
|
private static TaskPackPlan CreatePlan()
|
||||||
|
{
|
||||||
|
return new TaskPackPlan(
|
||||||
|
new TaskPackPlanMetadata("sample-pack", "1.0.0", null, Array.Empty<string>()),
|
||||||
|
new Dictionary<string, JsonNode?>(StringComparer.Ordinal),
|
||||||
|
Array.Empty<TaskPackPlanStep>(),
|
||||||
|
hash: "hash",
|
||||||
|
approvals: Array.Empty<TaskPackPlanApproval>(),
|
||||||
|
secrets: Array.Empty<TaskPackPlanSecret>(),
|
||||||
|
outputs: Array.Empty<TaskPackPlanOutput>(),
|
||||||
|
failurePolicy: new TaskPackPlanFailurePolicy(1, 1, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<ArtifactManifestModel> ReadManifestAsync(string runPath)
|
||||||
|
{
|
||||||
|
var json = await File.ReadAllTextAsync(Path.Combine(runPath, "artifact-manifest.json"), TestContext.Current.CancellationToken);
|
||||||
|
return JsonSerializer.Deserialize<ArtifactManifestModel>(json, new JsonSerializerOptions(JsonSerializerDefaults.Web))!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(artifactsRoot))
|
||||||
|
{
|
||||||
|
Directory.Delete(artifactsRoot, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed record ArtifactManifestModel(string RunId, DateTimeOffset UploadedAt, List<ArtifactRecordModel> Outputs);
|
||||||
|
|
||||||
|
private sealed record ArtifactRecordModel(string Name, string Type, string? SourcePath, string? StoredPath, string Status, string? Notes);
|
||||||
|
}
|
||||||
@@ -51,7 +51,13 @@ builder.Services.AddSingleton<IPackRunStepExecutor, NoopPackRunStepExecutor>();
|
|||||||
builder.Services.AddSingleton<PackRunExecutionGraphBuilder>();
|
builder.Services.AddSingleton<PackRunExecutionGraphBuilder>();
|
||||||
builder.Services.AddSingleton<PackRunSimulationEngine>();
|
builder.Services.AddSingleton<PackRunSimulationEngine>();
|
||||||
builder.Services.AddSingleton<PackRunProcessor>();
|
builder.Services.AddSingleton<PackRunProcessor>();
|
||||||
builder.Services.AddSingleton<IPackRunArtifactUploader, LoggingPackRunArtifactUploader>();
|
builder.Services.AddSingleton<IPackRunArtifactUploader>(sp =>
|
||||||
|
{
|
||||||
|
var options = sp.GetRequiredService<IOptions<PackRunWorkerOptions>>().Value;
|
||||||
|
var timeProvider = sp.GetService<TimeProvider>();
|
||||||
|
var logger = sp.GetRequiredService<ILogger<FilesystemPackRunArtifactUploader>>();
|
||||||
|
return new FilesystemPackRunArtifactUploader(options.ArtifactsPath, timeProvider, logger);
|
||||||
|
});
|
||||||
builder.Services.AddHostedService<PackRunWorkerService>();
|
builder.Services.AddHostedService<PackRunWorkerService>();
|
||||||
|
|
||||||
var host = builder.Build();
|
var host = builder.Build();
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ public sealed class PackRunWorkerOptions
|
|||||||
{
|
{
|
||||||
public TimeSpan IdleDelay { get; set; } = TimeSpan.FromSeconds(1);
|
public TimeSpan IdleDelay { get; set; } = TimeSpan.FromSeconds(1);
|
||||||
|
|
||||||
public string QueuePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "queue");
|
public string QueuePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "queue");
|
||||||
|
|
||||||
public string ArchivePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "queue", "archive");
|
public string ArchivePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "queue", "archive");
|
||||||
|
|
||||||
public string ApprovalStorePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "approvals");
|
public string ApprovalStorePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "approvals");
|
||||||
|
|
||||||
public string RunStatePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "state", "runs");
|
public string RunStatePath { get; set; } = Path.Combine(AppContext.BaseDirectory, "state", "runs");
|
||||||
|
|
||||||
|
public string ArtifactsPath { get; set; } = Path.Combine(AppContext.BaseDirectory, "artifacts");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Google.Cloud.Kms.V1;
|
using Google.Cloud.Kms.V1;
|
||||||
using Google.Protobuf;
|
using Google.Protobuf;
|
||||||
|
using Google.Protobuf.WellKnownTypes;
|
||||||
|
|
||||||
namespace StellaOps.Cryptography.Kms;
|
namespace StellaOps.Cryptography.Kms;
|
||||||
|
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ internal sealed class Pkcs11InteropFacade : IPkcs11Facade
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
# ignore logout failures
|
// ignore logout failures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,9 +64,8 @@ public sealed class Pkcs11Options
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets an optional factory for advanced facade injection (testing, custom providers).
|
/// Gets or sets an optional factory for advanced facade injection (testing, custom providers).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<IServiceProvider, IPkcs11Facade>? FacadeFactory { get; set; }
|
internal Func<IServiceProvider, IPkcs11Facade>? FacadeFactory { get; set; }
|
||||||
|
|
||||||
private static TimeSpan EnsurePositive(TimeSpan value, TimeSpan fallback)
|
private static TimeSpan EnsurePositive(TimeSpan value, TimeSpan fallback)
|
||||||
=> value <= TimeSpan.Zero ? fallback : value;
|
=> value <= TimeSpan.Zero ? fallback : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,3 +5,22 @@ These binaries (libcrypto.so.1.1 and libssl.so.1.1) are bundled for Mongo2Go-bas
|
|||||||
Source package: https://launchpad.net/ubuntu/+archive/primary/+files/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
|
Source package: https://launchpad.net/ubuntu/+archive/primary/+files/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
|
||||||
|
|
||||||
Licensing follows the OpenSSL and SSLeay licenses that accompany the upstream package.
|
Licensing follows the OpenSSL and SSLeay licenses that accompany the upstream package.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
1. Point `LD_LIBRARY_PATH` at this directory before running any test suite that spins up Mongo2Go:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export LD_LIBRARY_PATH="$(git rev-parse --show-toplevel)/tests/native/openssl-1.1/linux-x64:${LD_LIBRARY_PATH:-}"
|
||||||
|
```
|
||||||
|
|
||||||
|
The helper in `tests/shared/OpenSslLegacyShim.cs` will append the path automatically when the tests run, but exporting the variable up-front avoids surprises when using custom harnesses (e.g., `dotnet test` filters).
|
||||||
|
|
||||||
|
2. Example one-shot command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
LD_LIBRARY_PATH="$(pwd)/tests/native/openssl-1.1/linux-x64" \
|
||||||
|
dotnet test src/Excititor/__Tests/StellaOps.Excititor.Worker.Tests/StellaOps.Excititor.Worker.Tests.csproj --nologo
|
||||||
|
```
|
||||||
|
|
||||||
|
3. CI runners should add the same directory to their environment or place the binaries on a globally accessible library path.
|
||||||
|
|||||||
Reference in New Issue
Block a user