chore(devops): dotnet release image + compose/bootstrap stabilization

Sprint SPRINT_20260417_024_DevOps_dotnet_release_image_stabilization.

- Dockerfile.platform + Dockerfile.dotnet-service adjustments for
  deterministic layer ordering and cache-friendly publish.
- devops/release/components.json updates.
- devops/compose: .env, README, legacy + stella-services docker-compose,
  stellaops env example, postgres-init 04/04b/15/16 authority + release
  schemas, setup.bootstrap.local.yaml.
- Gitea build_release.py script.
- scripts/register-local-integrations.ps1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
master
2026-04-19 14:43:23 +03:00
parent c7109ed214
commit 24be2f2268
15 changed files with 57 additions and 132 deletions

View File

@@ -295,8 +295,8 @@ class ReleaseBuilder:
build_args.update({
"PROJECT": component["project"],
"ENTRYPOINT_DLL": component["entrypoint"],
"SDK_IMAGE": docker_cfg.get("sdkImage", "mcr.microsoft.com/dotnet/nightly/sdk:10.0"),
"RUNTIME_IMAGE": docker_cfg.get("runtimeImage", "gcr.io/distroless/dotnet/aspnet:latest"),
"SDK_IMAGE": docker_cfg.get("sdkImage", "mcr.microsoft.com/dotnet/sdk:10.0"),
"RUNTIME_IMAGE": docker_cfg.get("runtimeImage", "mcr.microsoft.com/dotnet/aspnet:10.0"),
})
elif kind == "angular-ui":
build_args.update({

View File

@@ -54,6 +54,7 @@ STELLAOPS_CA_BUNDLE_VOLUME=./combined-ca-bundle.crt:/etc/ssl/certs/ca-certificat
AUTHORITY_ISSUER=https://authority.stella-ops.local/
AUTHORITY_PORT=8440
AUTHORITY_OFFLINE_CACHE_TOLERANCE=00:30:00
STELLAOPS_ADMIN_PASS=Admin@Stella2026!
# Signer
SIGNER_POE_INTROSPECT_URL=http://authority.stella-ops.local/.well-known/openid-configuration

View File

@@ -148,6 +148,14 @@ curl -fsS http://127.1.1.3:8080/status
docker compose -f docker-compose.stella-ops.yml logs -f scanner-web
```
For the local compose setup flow, the template now includes `STELLAOPS_ADMIN_PASS=Admin@Stella2026!`.
Use `admin` / `Admin@Stella2026!` to complete the first-run setup wizard and to run the live browser helpers under `src/Web/StellaOps.Web/scripts/`.
Keep that value only for local/dev usage; override it before sharing the stack with anyone else.
The live browser helpers intentionally ignore local self-signed/dev certificates
for UI automation only. Product runtime TLS validation for advisory feeds,
mirror sync, and other service-to-service calls remains strict and is not
exempted by this local browser setting.
### Router Frontdoor Configuration
`router-gateway` uses the microservice-first route table in `router-gateway-local.json`,
@@ -490,7 +498,7 @@ PLAYWRIGHT_BASE_URL=https://stella-ops.local \
| `PLAYWRIGHT_BASE_URL` | `https://stella-ops.local` | Target Stella Ops instance |
| `E2E_RUN_ID` | `run1` | Unique suffix for test integration names (avoids duplicates across runs) |
| `STELLAOPS_ADMIN_USER` | `admin` | Login username |
| `STELLAOPS_ADMIN_PASS` | `Admin@Stella2026!` | Login password |
| `STELLAOPS_ADMIN_PASS` | `Admin@Stella2026!` | Local compose default password for the administrator account created during setup |
**Key files:**

View File

@@ -516,8 +516,8 @@ services:
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__Type: "standard"
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__AssemblyName: "StellaOps.Authority.Plugin.Standard"
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__Enabled: "true"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__ID: "demo-prod"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__DISPLAYNAME: "Demo Production"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__ID: "default"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__DISPLAYNAME: "Default Tenant"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__STATUS: "active"
<<: [*router-microservice-defaults, *gc-heavy]
Router__Enabled: "${AUTHORITY_ROUTER_ENABLED:-true}"
@@ -849,6 +849,7 @@ services:
CONCELIER_AUTHORITY__BASEURL: "https://authority.stella-ops.local"
CONCELIER_AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
CONCELIER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "${AUTHORITY_OFFLINE_CACHE_TOLERANCE:-00:30:00}"
STELLAOPS_BOOTSTRAP_KEY: "${AUTHORITY_BOOTSTRAP_APIKEY:-stellaops-dev-bootstrap-key}"
Router__Enabled: "${CONCELIER_ROUTER_ENABLED:-true}"
Router__Messaging__ConsumerGroup: "concelier"
CONCELIER_IMPORT__STAGINGROOT: "/var/lib/concelier/import"

View File

@@ -347,8 +347,8 @@ services:
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__Type: "standard"
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__AssemblyName: "StellaOps.Authority.Plugin.Standard"
STELLAOPS_AUTHORITY_AUTHORITY__PLUGINS__DESCRIPTORS__standard__Enabled: "true"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__ID: "demo-prod"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__DISPLAYNAME: "Demo Production"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__ID: "default"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__DISPLAYNAME: "Default Tenant"
STELLAOPS_AUTHORITY_AUTHORITY__TENANTS__0__STATUS: "active"
<<: [*router-microservice-defaults, *gc-heavy]
Router__Enabled: "${AUTHORITY_ROUTER_ENABLED:-true}"
@@ -659,6 +659,7 @@ services:
CONCELIER_AUTHORITY__BASEURL: "https://authority.stella-ops.local"
CONCELIER_AUTHORITY__RESILIENCE__ALLOWOFFLINECACHEFALLBACK: "true"
CONCELIER_AUTHORITY__RESILIENCE__OFFLINECACHETOLERANCE: "${AUTHORITY_OFFLINE_CACHE_TOLERANCE:-00:30:00}"
STELLAOPS_BOOTSTRAP_KEY: "${AUTHORITY_BOOTSTRAP_APIKEY:-stellaops-dev-bootstrap-key}"
Router__Enabled: "${CONCELIER_ROUTER_ENABLED:-true}"
Router__Messaging__ConsumerGroup: "concelier"
CONCELIER_IMPORT__STAGINGROOT: "/var/lib/concelier/import"

View File

@@ -45,6 +45,11 @@ ROUTER_AUTHORITY_CLAIMS_OVERRIDES_URL=http://authority.stella-ops.local
AUTHORITY_ISSUER=https://authority.stella-ops.local/
AUTHORITY_PORT=8440
AUTHORITY_OFFLINE_CACHE_TOLERANCE=00:30:00
AUTHORITY_BOOTSTRAP_APIKEY=stellaops-dev-bootstrap-key
# Local first-run bootstrap admin used by the setup wizard and live browser helpers.
# Keep this value only for local/dev compose usage and rotate it for any shared environment.
STELLAOPS_ADMIN_PASS=Admin@Stella2026!
# Signer
SIGNER_POE_INTROSPECT_URL=http://authority.stella-ops.local/.well-known/openid-configuration
@@ -170,8 +175,8 @@ SM_REMOTE_HSM_TIMEOUT=30000
# DEMO DATA SEEDING
# =============================================================================
# Enable demo data seeding API endpoint (disabled in production)
STELLAOPS_ENABLE_DEMO_SEED=true
# Optional manual demo data seeding API endpoint. Keep disabled for truthful default installs.
STELLAOPS_ENABLE_DEMO_SEED=false
# =============================================================================
# NETWORKING

View File

@@ -466,11 +466,11 @@ CREATE INDEX IF NOT EXISTS idx_verdict_digest
COMMENT ON TABLE authority.verdict_manifests IS 'VEX verdict manifests for deterministic replay verification';
-- ============================================================================
-- SECTION 4b: Seed Default Tenant
-- SECTION 4b: Bootstrap Default Tenant
-- ============================================================================
INSERT INTO authority.tenants (tenant_id, name, display_name, status)
VALUES ('demo-prod', 'Production', 'Demo Production', 'active')
VALUES ('default', 'Default', 'Default Tenant', 'active')
ON CONFLICT (tenant_id) DO NOTHING;
-- ============================================================================
@@ -618,51 +618,8 @@ END
$$;
-- ============================================================================
-- SECTION 8: Demo Seed Data
-- SECTION 8: Bootstrap Notes
-- ============================================================================
-- Roles for demo-prod tenant
INSERT INTO authority.roles (id, tenant_id, name, display_name, description, is_system)
VALUES
('a0000002-0000-0000-0000-000000000001', 'demo-prod', 'admin', 'Administrator', 'Full platform access', true),
('a0000002-0000-0000-0000-000000000002', 'demo-prod', 'operator', 'Operator', 'Release and deployment operations', true),
('a0000002-0000-0000-0000-000000000003', 'demo-prod', 'viewer', 'Viewer', 'Read-only access', true)
ON CONFLICT (tenant_id, name) DO NOTHING;
-- OAuth Clients
INSERT INTO authority.clients (id, client_id, display_name, description, enabled, redirect_uris, post_logout_redirect_uris, allowed_scopes, allowed_grant_types, require_client_secret, require_pkce, properties)
VALUES
('demo-client-ui', 'stella-ops-ui', 'Stella Ops Console', 'Web UI application', true,
ARRAY['https://stella-ops.local/auth/callback', 'https://stella-ops.local/auth/silent-refresh', 'https://127.1.0.1/auth/callback', 'https://127.1.0.1/auth/silent-refresh'],
ARRAY['https://stella-ops.local/', 'https://127.1.0.1/'],
ARRAY['openid', 'profile', 'email', 'offline_access',
'ui.read', 'ui.admin', 'ui.preferences.read', 'ui.preferences.write',
'authority:tenants.read', 'authority:tenants.write',
'authority:users.read', 'authority:users.write',
'authority:roles.read', 'authority:roles.write',
'authority:clients.read', 'authority:clients.write',
'authority:tokens.read', 'authority:tokens.revoke',
'authority:branding.read', 'authority:branding.write',
'authority.audit.read',
'graph:read', 'sbom:read', 'scanner:read',
'policy:read', 'policy:simulate', 'policy:author', 'policy:review', 'policy:approve',
'policy:run', 'policy:activate', 'policy:audit', 'policy:edit', 'policy:operate', 'policy:publish',
'airgap:seal', 'airgap:status:read',
'orch:read', 'analytics.read', 'advisory:read', 'advisory-ai:view', 'advisory-ai:operate',
'vex:read', 'vexhub:read',
'exceptions:read', 'exceptions:approve', 'aoc:verify', 'findings:read',
'release:read', 'release:write', 'release:publish', 'scheduler:read', 'scheduler:operate',
'notify.viewer', 'notify.operator', 'notify.admin', 'notify.escalate',
'evidence:read',
'export.viewer', 'export.operator', 'export.admin',
'vuln:view', 'vuln:investigate', 'vuln:operate', 'vuln:audit',
'platform.context.read', 'platform.context.write',
'platform.idp.read', 'platform.idp.admin',
'doctor:run', 'doctor:admin', 'ops.health',
'integration:read', 'integration:write', 'integration:operate', 'registry.admin',
'timeline:read', 'timeline:write',
'signer:read', 'signer:sign', 'signer:rotate', 'signer:admin',
'trust:read', 'trust:write', 'trust:admin'],
ARRAY['authorization_code', 'refresh_token'],
false, true, '{"tenant": "demo-prod"}'::jsonb)
ON CONFLICT (client_id) DO NOTHING;
-- First-party clients are seeded by the Authority standard plugin at runtime.
-- The first administrator is created through the setup wizard, not compose SQL.

View File

@@ -349,11 +349,11 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_verdict_replay ON authority.verdict_manife
CREATE INDEX IF NOT EXISTS idx_verdict_digest ON authority.verdict_manifests(manifest_digest);
-- ============================================================================
-- SECTION 5: Seed Data
-- SECTION 5: Bootstrap Default Tenant
-- ============================================================================
INSERT INTO authority.tenants (tenant_id, name, display_name, status)
VALUES ('demo-prod', 'Production', 'Demo Production', 'active')
VALUES ('default', 'Default', 'Default Tenant', 'active')
ON CONFLICT (tenant_id) DO NOTHING;
-- ============================================================================
@@ -448,49 +448,8 @@ DO $$ BEGIN
END $$;
-- ============================================================================
-- SECTION 9: Demo Seed Data
-- SECTION 9: Bootstrap Notes
-- ============================================================================
INSERT INTO authority.roles (id, tenant_id, name, display_name, description, is_system)
VALUES
('a0000002-0000-0000-0000-000000000001', 'demo-prod', 'admin', 'Administrator', 'Full platform access', true),
('a0000002-0000-0000-0000-000000000002', 'demo-prod', 'operator', 'Operator', 'Release and deployment operations', true),
('a0000002-0000-0000-0000-000000000003', 'demo-prod', 'viewer', 'Viewer', 'Read-only access', true)
ON CONFLICT (tenant_id, name) DO NOTHING;
INSERT INTO authority.clients (id, client_id, display_name, description, enabled, redirect_uris, post_logout_redirect_uris, allowed_scopes, allowed_grant_types, require_client_secret, require_pkce, properties)
VALUES
('demo-client-ui', 'stella-ops-ui', 'Stella Ops Console', 'Web UI application', true,
ARRAY['https://stella-ops.local/auth/callback', 'https://stella-ops.local/auth/silent-refresh', 'https://127.1.0.1/auth/callback', 'https://127.1.0.1/auth/silent-refresh'],
ARRAY['https://stella-ops.local/', 'https://127.1.0.1/'],
ARRAY['openid', 'profile', 'email', 'offline_access',
'ui.read', 'ui.admin', 'ui.preferences.read', 'ui.preferences.write',
'authority:tenants.read', 'authority:tenants.write',
'authority:users.read', 'authority:users.write',
'authority:roles.read', 'authority:roles.write',
'authority:clients.read', 'authority:clients.write',
'authority:tokens.read', 'authority:tokens.revoke',
'authority:branding.read', 'authority:branding.write',
'authority.audit.read',
'graph:read', 'sbom:read', 'scanner:read',
'policy:read', 'policy:simulate', 'policy:author', 'policy:review', 'policy:approve',
'policy:run', 'policy:activate', 'policy:audit', 'policy:edit', 'policy:operate', 'policy:publish',
'airgap:seal', 'airgap:status:read',
'orch:read', 'analytics.read', 'advisory:read', 'advisory-ai:view', 'advisory-ai:operate',
'vex:read', 'vexhub:read',
'exceptions:read', 'exceptions:approve', 'aoc:verify', 'findings:read',
'release:read', 'release:write', 'release:publish', 'scheduler:read', 'scheduler:operate',
'notify.viewer', 'notify.operator', 'notify.admin', 'notify.escalate',
'evidence:read',
'export.viewer', 'export.operator', 'export.admin',
'vuln:view', 'vuln:investigate', 'vuln:operate', 'vuln:audit',
'platform.context.read', 'platform.context.write',
'platform.idp.read', 'platform.idp.admin',
'doctor:run', 'doctor:admin', 'ops.health',
'integration:read', 'integration:write', 'integration:operate', 'registry.admin',
'timeline:read', 'timeline:write',
'signer:read', 'signer:sign', 'signer:rotate', 'signer:admin',
'trust:read', 'trust:write', 'trust:admin'],
ARRAY['authorization_code', 'refresh_token'],
false, true, '{"tenant": "demo-prod"}'::jsonb)
ON CONFLICT (client_id) DO NOTHING;
-- First-party clients are seeded by the Authority standard plugin at runtime.
-- The first administrator is created through the setup wizard, not compose SQL.

View File

@@ -70,19 +70,5 @@ CREATE INDEX IF NOT EXISTS idx_control_bundles_tenant_name
CREATE INDEX IF NOT EXISTS idx_control_bundles_tenant_updated
ON release.control_bundles (tenant_id, updated_at DESC, id);
-- Seed demo context data for local development
INSERT INTO platform.context_regions (region_id, display_name, sort_order, enabled)
VALUES
('us-east', 'US East', 1, true),
('us-west', 'US West', 2, true),
('eu-west', 'EU West', 3, true)
ON CONFLICT (region_id) DO NOTHING;
INSERT INTO platform.context_environments (environment_id, region_id, environment_type, display_name, sort_order, enabled)
VALUES
('dev', 'us-east', 'development', 'Development', 1, true),
('stage', 'us-east', 'staging', 'Staging', 2, true),
('prod-us-east', 'us-east', 'production', 'Production US East', 3, true),
('prod-us-west', 'us-west', 'production', 'Production US West', 4, true),
('prod-eu-west', 'eu-west', 'production', 'Production EU West', 5, true)
ON CONFLICT (environment_id) DO NOTHING;
-- Context regions/environments are intentionally left empty on fresh installs.
-- The setup and admin surfaces create truthful operator-owned state as needed.

View File

@@ -22,10 +22,14 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_shared_tenants_single_default
ON shared.tenants (is_default)
WHERE is_default;
-- Seed shared tenant for local dev
INSERT INTO shared.tenants (tenant_id, name, display_name, status)
VALUES ('demo-prod', 'Production', 'Demo Production', 'active')
ON CONFLICT (tenant_id) DO NOTHING;
-- Seed the generic default tenant required by release/shared foreign keys.
INSERT INTO shared.tenants (tenant_id, name, display_name, is_default, status)
VALUES ('default', 'Default', 'Default Tenant', true, 'active')
ON CONFLICT (tenant_id) DO UPDATE
SET name = EXCLUDED.name,
display_name = EXCLUDED.display_name,
is_default = EXCLUDED.is_default,
status = EXCLUDED.status;
-- Release schemas
CREATE SCHEMA IF NOT EXISTS release;

View File

@@ -1,3 +1,5 @@
# Manual CLI bootstrap example only.
# Fresh local installs should use the UI setup wizard instead of this file.
version: "1"
database:
@@ -15,7 +17,7 @@ cache:
custom:
users.superuser.username: admin
users.superuser.email: admin@stella-ops.local
users.superuser.password: Admin@Stella2026!
users.superuser.password: CHANGE-ME-BEFORE-MANUAL-CLI-USE
users.superuser.displayName: Stella Admin
authority.provider: standard
crypto.provider: default

View File

@@ -5,7 +5,7 @@
# ============================================================================
# Stage 1: SDK Build - Build ALL Projects and Crypto Plugins
# ============================================================================
FROM mcr.microsoft.com/dotnet/sdk:10.0-preview AS build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src
# Copy solution and project files for dependency restore
@@ -98,7 +98,7 @@ COPY etc/crypto-plugins-manifest.json /app/publish/etc/
# ============================================================================
# Stage 2: Runtime Base - Contains ALL Crypto Plugins
# ============================================================================
FROM mcr.microsoft.com/dotnet/aspnet:10.0-preview AS runtime-base
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime-base
WORKDIR /app
# Install dependencies for crypto providers

View File

@@ -3,8 +3,8 @@
"platforms": ["linux/amd64", "linux/arm64"],
"defaultChannel": "edge",
"docker": {
"sdkImage": "mcr.microsoft.com/dotnet/nightly/sdk:10.0",
"runtimeImage": "mcr.microsoft.com/dotnet/nightly/aspnet:10.0",
"sdkImage": "mcr.microsoft.com/dotnet/sdk:10.0",
"runtimeImage": "mcr.microsoft.com/dotnet/aspnet:10.0",
"nodeImage": "node:20.14.0-bookworm",
"nginxImage": "nginx:1.27-alpine"
},

View File

@@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1.7-labs
ARG SDK_IMAGE=mcr.microsoft.com/dotnet/nightly/sdk:10.0
ARG RUNTIME_IMAGE=gcr.io/distroless/dotnet/aspnet:latest
ARG SDK_IMAGE=mcr.microsoft.com/dotnet/sdk:10.0
ARG RUNTIME_IMAGE=mcr.microsoft.com/dotnet/aspnet:10.0
ARG PROJECT
ARG ENTRYPOINT_DLL

View File

@@ -7,7 +7,8 @@
any missing local-capable providers, then runs test and health checks for
each entry so the catalog converges to a ready local lane.
.PARAMETER Tenant
Tenant identifier used for the catalog operations. Defaults to demo-prod.
Tenant identifier used for the catalog operations. Defaults to default; override
it if your setup flow created a different tenant identifier.
.PARAMETER BaseUrl
Base URL for the local Integrations API. Defaults to the host-mapped
integrations-web endpoint.
@@ -24,7 +25,7 @@
#>
[CmdletBinding()]
param(
[string]$Tenant = 'demo-prod',
[string]$Tenant = 'default',
[string]$BaseUrl = 'http://127.1.0.42',
[switch]$IncludeGitLab,
[switch]$IncludeGitLabRegistry,