search and ai stabilization work, localization stablized.
This commit is contained in:
@@ -85,6 +85,9 @@ Implemented in `src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/KnowledgeSea
|
||||
## API contract
|
||||
### Search
|
||||
- `POST /v1/advisory-ai/search`
|
||||
- Legacy notice: endpoint emits deprecation metadata and points to unified replacement `POST /v1/search/query`.
|
||||
- Authorization: `advisory-ai:operate` (or `advisory-ai:admin`).
|
||||
- Filter validation: `filters.type` allowlist is strictly enforced (`docs`, `api`, `doctor`); unsupported values return HTTP 400.
|
||||
- Request:
|
||||
- `q` (required), `k`, `filters.type|product|version|service|tags`, `includeDebug`.
|
||||
- Response:
|
||||
@@ -93,6 +96,40 @@ Implemented in `src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/KnowledgeSea
|
||||
### Rebuild
|
||||
- `POST /v1/advisory-ai/index/rebuild`
|
||||
- Rebuilds AKS deterministically from local docs/specs/doctor metadata.
|
||||
- Authorization: `advisory-ai:admin`.
|
||||
|
||||
## Localization runtime contract
|
||||
- AdvisoryAI WebService localization is enabled through `AddStellaOpsLocalization(...)`, embedded service bundles (`Translations/*.advisoryai.json`), and `AddRemoteTranslationBundles()`.
|
||||
- Locale behavior follows backend contract: `X-Locale` -> `Accept-Language` -> default locale.
|
||||
- Supported service locales for this rollout slice: `en-US`, `de-DE`.
|
||||
- Remote translation bundles are enabled when Platform base URL is configured via `STELLAOPS_PLATFORM_URL`, `Platform:BaseUrl`, or `StellaOps:Platform:BaseUrl`.
|
||||
- Localized validation keys used by both `POST /v1/advisory-ai/search` and `POST /v1/search/query`:
|
||||
- `advisoryai.validation.q_required`
|
||||
- `advisoryai.validation.q_max_512`
|
||||
- `advisoryai.validation.tenant_required`
|
||||
|
||||
## Unified search interoperability
|
||||
- Unified endpoint: `POST /v1/search/query`.
|
||||
- Query validation: `q` is required and capped at 512 characters.
|
||||
- Tenant validation: unified and AKS search endpoints now require tenant context (`X-StellaOps-Tenant` or `X-Tenant-Id`) and bind tenant into backend search filters.
|
||||
- Unified filter allowlists are enforced server-side:
|
||||
- Supported `filters.domains`: `knowledge`, `findings`, `vex`, `policy`, `platform`.
|
||||
- Supported `filters.entityTypes`: `docs`, `api`, `doctor`, `finding`, `vex_statement`, `policy_rule`, `platform_entity`.
|
||||
- Unsupported domain/entity filter values are rejected with HTTP 400; they are not silently broadened to an unfiltered query.
|
||||
- Unified index lifecycle:
|
||||
- Manual rebuild endpoint: `POST /v1/search/index/rebuild`.
|
||||
- Optional background refresh loop is available via `KnowledgeSearchOptions` (`UnifiedAutoIndexEnabled`, `UnifiedAutoIndexOnStartup`, `UnifiedIndexRefreshIntervalSeconds`).
|
||||
- Unified ingestion adapters now ingest from deterministic snapshot files (findings/vex/policy) plus platform catalog projection, replacing hardcoded sample chunks.
|
||||
- Default snapshot paths:
|
||||
- `src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/findings.snapshot.json`
|
||||
- `src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/vex.snapshot.json`
|
||||
- `src/AdvisoryAI/StellaOps.AdvisoryAI/UnifiedSearch/Snapshots/policy.snapshot.json`
|
||||
- Ranking determinism:
|
||||
- Freshness boost is disabled by default and only applies when `UnifiedFreshnessBoostEnabled` is explicitly enabled.
|
||||
- Ranking no longer depends on ambient wall-clock time unless that option is enabled.
|
||||
- Query telemetry:
|
||||
- Unified search emits hashed query telemetry (`SHA-256` query hash, intent, domain weights, latency, top domains) via `IUnifiedSearchTelemetrySink`.
|
||||
- Web fallback behavior: when unified search fails, `UnifiedSearchClient` falls back to legacy AKS (`/v1/advisory-ai/search`) and maps grouped legacy results into unified cards (`diagnostics.mode = legacy-fallback`).
|
||||
|
||||
## Web behavior
|
||||
Global search now consumes AKS and supports:
|
||||
@@ -143,7 +180,219 @@ stella advisoryai index rebuild --json
|
||||
dotnet test src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj
|
||||
```
|
||||
|
||||
## Search improvement sprints (G1–G10) — testing infrastructure guide
|
||||
|
||||
Ten search improvement sprints (SPRINT_20260224_101 through SPRINT_20260224_110) were implemented as a batch. This section documents how to set up infrastructure and run the full test suite.
|
||||
|
||||
### Sprint inventory
|
||||
|
||||
| Sprint | Gap | Topic | Module(s) |
|
||||
| --- | --- | --- | --- |
|
||||
| 101 | G5 | FTS English stemming + trigram fuzzy | AdvisoryAI (backend) |
|
||||
| 102 | G1 | ONNX semantic vector encoder | AdvisoryAI (backend) |
|
||||
| 103 | G2 | Cross-domain live-data adapters | AdvisoryAI (backend) |
|
||||
| 104 | G3 | LLM-grounded synthesis engine | AdvisoryAI (backend) |
|
||||
| 105 | G4 | Search onboarding + guided discovery + "Did you mean?" | FE + AdvisoryAI |
|
||||
| 106 | G6 | Search personalization (popularity boost, role-based bias, history) | AdvisoryAI + FE |
|
||||
| 107 | G7 | Search → Chat bridge ("Ask AI" button) | FE |
|
||||
| 108 | G8 | Inline result previews (expandable entity cards) | AdvisoryAI + FE |
|
||||
| 109 | G9 | Multilingual search (de/fr/es/ru FTS, language detection, localized doctor seeds) | AdvisoryAI + FE |
|
||||
| 110 | G10 | Search feedback loop (thumbs up/down, quality dashboard, query refinements) | AdvisoryAI + FE |
|
||||
|
||||
### Test projects and files
|
||||
|
||||
All backend tests live in a single test project:
|
||||
```
|
||||
src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj
|
||||
```
|
||||
|
||||
Key test files added by the search sprints:
|
||||
|
||||
| File | Coverage | Type |
|
||||
| --- | --- | --- |
|
||||
| `Integration/UnifiedSearchSprintIntegrationTests.cs` | All 10 sprints (87 tests) — endpoint auth, domain filtering, synthesis, suggestions, role-based bias, multilingual detection, feedback validation | Integration (WebApplicationFactory) |
|
||||
| `Integration/KnowledgeSearchEndpointsIntegrationTests.cs` | AKS endpoints: auth, search, localization, rebuild | Integration (WebApplicationFactory) |
|
||||
| `KnowledgeSearch/FtsRecallBenchmarkTests.cs` | G5-005: FTS recall benchmark (12 tests, 34-query fixture) | Benchmark |
|
||||
| `KnowledgeSearch/FtsRecallBenchmarkStore.cs` | In-memory FTS store simulating Simple vs English modes | Test harness |
|
||||
| `KnowledgeSearch/SemanticRecallBenchmarkTests.cs` | G1-004: Semantic recall benchmark (13 tests, 48-query fixture) | Benchmark |
|
||||
| `KnowledgeSearch/SemanticRecallBenchmarkStore.cs` | In-memory vector store with cosine similarity search | Test harness |
|
||||
| `UnifiedSearch/UnifiedSearchServiceTests.cs` | G8: Preview generation (7 tests) | Unit |
|
||||
|
||||
Test data fixtures (auto-copied to output via `TestData/*.json` glob in .csproj):
|
||||
- `TestData/fts-recall-benchmark.json` — 34 queries across exact/stemming/typos/short/natural categories
|
||||
- `TestData/semantic-recall-benchmark.json` — 48 queries across synonym/paraphrase/conceptual/acronym/exact categories
|
||||
|
||||
### Prerequisites to run
|
||||
|
||||
**Detailed infrastructure setup guide**: `src/AdvisoryAI/__Tests/INFRASTRUCTURE.md` — covers 4 tiers (in-process, live database, ONNX model, frontend E2E) with exact Docker commands, connection strings, extension requirements, and config examples.
|
||||
|
||||
**No external infrastructure needed for the in-process test suite.** All integration tests use `WebApplicationFactory<Program>` with stubbed services. Benchmarks use in-memory stores. No PostgreSQL, no Docker, no network access required.
|
||||
|
||||
Run the full suite:
|
||||
```bash
|
||||
dotnet test "src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj" -v normal
|
||||
```
|
||||
|
||||
Run only the search sprint integration tests:
|
||||
```bash
|
||||
dotnet test "src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj" \
|
||||
--filter "FullyQualifiedName~UnifiedSearchSprintIntegrationTests" -v normal
|
||||
```
|
||||
|
||||
Run only the FTS recall benchmark:
|
||||
```bash
|
||||
dotnet test "src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj" \
|
||||
--filter "FullyQualifiedName~FtsRecallBenchmarkTests" -v normal
|
||||
```
|
||||
|
||||
Run only the semantic recall benchmark:
|
||||
```bash
|
||||
dotnet test "src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj" \
|
||||
--filter "FullyQualifiedName~SemanticRecallBenchmarkTests" -v normal
|
||||
```
|
||||
|
||||
**For live database tests** (e.g., full AKS rebuild + query against real Postgres with pg_trgm/pgvector):
|
||||
```bash
|
||||
# Start the dedicated AKS test database
|
||||
docker compose -f devops/compose/docker-compose.advisoryai-knowledge-test.yml up -d
|
||||
|
||||
# Wait for health check
|
||||
docker compose -f devops/compose/docker-compose.advisoryai-knowledge-test.yml ps
|
||||
|
||||
# Prepare sources and rebuild index
|
||||
stella advisoryai sources prepare --json
|
||||
stella advisoryai index rebuild --json
|
||||
|
||||
# Run tests with the Live category (requires database)
|
||||
dotnet test "src/AdvisoryAI/__Tests/StellaOps.AdvisoryAI.Tests/StellaOps.AdvisoryAI.Tests.csproj" \
|
||||
--filter "Category=Live" -v normal
|
||||
```
|
||||
|
||||
Or use the full CI testing stack:
|
||||
```bash
|
||||
docker compose -f devops/compose/docker-compose.testing.yml --profile ci up -d
|
||||
```
|
||||
|
||||
### Database extensions required for live tests
|
||||
|
||||
The AKS knowledge test database init script (`devops/compose/postgres-init/advisoryai-knowledge-test/01_extensions.sql`) must enable:
|
||||
- `vector` (pgvector) — for `embedding_vec vector(384)` columns and cosine similarity
|
||||
- `pg_trgm` — for trigram fuzzy matching (`similarity()`, GIN trigram indexes)
|
||||
|
||||
These are already configured in the compose init scripts. If setting up a custom test database:
|
||||
```sql
|
||||
CREATE EXTENSION IF NOT EXISTS vector;
|
||||
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||
```
|
||||
|
||||
### Migrations required for search sprints
|
||||
|
||||
The search sprints added several migrations under `src/AdvisoryAI/StellaOps.AdvisoryAI/Storage/Migrations/`:
|
||||
|
||||
| Migration | Sprint | Content |
|
||||
| --- | --- | --- |
|
||||
| `004_fts_english_config.sql` | G5 (101) | `body_tsv_en` tsvector column + GIN index, pg_trgm extension + trigram indexes |
|
||||
| `005_search_feedback.sql` | G10 (110) | `search_feedback` + `search_quality_alerts` tables |
|
||||
| `005_search_analytics.sql` | G6 (106) | `search_events` + `search_history` tables |
|
||||
| `007_multilingual_fts.sql` | G9 (109) | `body_tsv_de`, `body_tsv_fr`, `body_tsv_es`, `body_tsv_ru` tsvector columns + GIN indexes |
|
||||
|
||||
All migrations are idempotent (IF NOT EXISTS guards). They run automatically via `EnsureSchemaAsync()` at service startup.
|
||||
|
||||
### Frontend tests
|
||||
|
||||
Frontend changes span `src/Web/StellaOps.Web/`. To run Angular unit tests:
|
||||
```bash
|
||||
cd src/Web/StellaOps.Web
|
||||
npm install
|
||||
npm run test:ci
|
||||
```
|
||||
|
||||
For E2E tests (requires the full stack running):
|
||||
```bash
|
||||
cd src/Web/StellaOps.Web
|
||||
npx playwright install
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
Relevant E2E config: `src/Web/StellaOps.Web/playwright.e2e.config.ts`.
|
||||
|
||||
### InternalsVisibleTo
|
||||
|
||||
The production assembly `StellaOps.AdvisoryAI` grants `InternalsVisibleTo` to `StellaOps.AdvisoryAI.Tests` (see `src/AdvisoryAI/StellaOps.AdvisoryAI/Properties/AssemblyInfo.cs`). This allows tests to access `internal` types including:
|
||||
- `IVectorEncoder`, `DeterministicHashVectorEncoder`, `OnnxVectorEncoder`
|
||||
- `ISynthesisEngine`, `SynthesisTemplateEngine`, `CompositeSynthesisEngine`, `LlmSynthesisEngine`
|
||||
- `IntentClassifier`, `QueryLanguageDetector`, `MultilingualIntentKeywords`, `DomainWeightCalculator`
|
||||
- `SearchAnalyticsService`, `SearchQualityMonitor`
|
||||
- `WeightedRrfFusion`, `UnifiedSearchService`
|
||||
- `IKnowledgeSearchStore`, `KnowledgeChunkRow`
|
||||
|
||||
### Key interfaces to stub in integration tests
|
||||
|
||||
| Interface | Purpose | Typical stub behavior |
|
||||
| --- | --- | --- |
|
||||
| `IKnowledgeSearchService` | AKS search | Return hardcoded results per query |
|
||||
| `IKnowledgeIndexer` | AKS index rebuild | Return fixed summary counts |
|
||||
| `IUnifiedSearchService` | Unified search | Return entity cards with domain filtering |
|
||||
| `IUnifiedSearchIndexer` | Unified index rebuild | Return fixed summary |
|
||||
| `ISynthesisEngine` | AI synthesis | Return template-based synthesis |
|
||||
| `IVectorEncoder` | Embedding generation | Use `DeterministicHashVectorEncoder` or `EmptyVectorEncoder` |
|
||||
| `IKnowledgeSearchStore` | FTS/vector storage | Use `DeterministicBenchmarkStore` or `FtsRecallBenchmarkStore` |
|
||||
|
||||
### Test categories and filtering
|
||||
|
||||
Use `[Trait("Category", TestCategories.XXX)]` to categorize tests. Key categories:
|
||||
- `Unit` — fast, in-memory, no external deps (default for most tests)
|
||||
- `Integration` — uses `WebApplicationFactory` or test containers
|
||||
- `Performance` — benchmarks (FTS recall, semantic recall)
|
||||
- `Live` — requires running database (skip in standard CI)
|
||||
|
||||
Filter examples:
|
||||
```bash
|
||||
# All except Live
|
||||
dotnet test ... --filter "Category!=Live"
|
||||
|
||||
# Only integration
|
||||
dotnet test ... --filter "Category=Integration"
|
||||
|
||||
# Specific test class
|
||||
dotnet test ... --filter "FullyQualifiedName~FtsRecallBenchmarkTests"
|
||||
```
|
||||
|
||||
### Localized doctor seeds
|
||||
|
||||
Doctor check content is available in 3 locales:
|
||||
- `doctor-search-seed.json` — English (base, 8 checks)
|
||||
- `doctor-search-seed.de.json` — German (de-DE)
|
||||
- `doctor-search-seed.fr.json` — French (fr-FR)
|
||||
|
||||
The `KnowledgeIndexer.IngestDoctorAsync()` method auto-discovers locale files via `DoctorSearchSeedLoader.LoadLocalized()` and ingests locale-tagged chunks alongside English. This enables German/French FTS queries to match doctor check content.
|
||||
|
||||
### Configuration options added by search sprints
|
||||
|
||||
All in `KnowledgeSearchOptions` (`src/AdvisoryAI/StellaOps.AdvisoryAI/KnowledgeSearch/KnowledgeSearchOptions.cs`):
|
||||
|
||||
| Option | Default | Sprint | Purpose |
|
||||
| --- | --- | --- | --- |
|
||||
| `FtsLanguageConfig` | `"english"` | G5 | Primary FTS text search config |
|
||||
| `FuzzyFallbackEnabled` | `true` | G5 | Enable pg_trgm fuzzy fallback |
|
||||
| `MinFtsResultsForFuzzyFallback` | `3` | G5 | Threshold for fuzzy activation |
|
||||
| `FuzzySimilarityThreshold` | `0.3` | G5 | pg_trgm similarity cutoff |
|
||||
| `VectorEncoderType` | `"hash"` | G1 | `"hash"` or `"onnx"` |
|
||||
| `OnnxModelPath` | `"models/all-MiniLM-L6-v2.onnx"` | G1 | Path to ONNX model file |
|
||||
| `LlmSynthesisEnabled` | `false` | G3 | Enable LLM-grounded synthesis |
|
||||
| `SynthesisTimeoutMs` | `5000` | G3 | LLM synthesis timeout |
|
||||
| `LlmAdapterBaseUrl` | `null` | G3 | LLM adapter service URL |
|
||||
| `LlmProviderId` | `null` | G3 | LLM provider selection |
|
||||
| `PopularityBoostEnabled` | `false` | G6 | Enable click-weighted ranking |
|
||||
| `PopularityBoostWeight` | `0.1` | G6 | Popularity boost factor |
|
||||
| `RoleBasedBiasEnabled` | `false` | G6 | Enable scope-based domain weighting |
|
||||
| `FtsLanguageConfigs` | `{}` | G9 | Per-locale FTS config map |
|
||||
|
||||
## Known limitations and follow-ups
|
||||
- YAML OpenAPI ingestion is not included in MVP.
|
||||
- End-to-end benchmark against live Postgres-backed AKS service is planned as a follow-up CI lane.
|
||||
- Optional external embedding providers can be added later without changing API contracts.
|
||||
- ONNX model file (`all-MiniLM-L6-v2.onnx`, ~80MB) must be provisioned separately for deployments opting into `VectorEncoderType=onnx`. Air-gap bundles must include the model.
|
||||
- Doctor seed localization covers de-DE and fr-FR only. Other locales (es-ES, ru-RU, bg-BG, etc.) use English fallback.
|
||||
- Search quality dashboard deferred items: low-quality results table, top queries table, 30-day trend chart (require additional backend aggregation queries).
|
||||
- Periodic `SearchQualityMonitor` background job not yet wired (zero-result alerting runs on-demand via metrics endpoint).
|
||||
|
||||
@@ -235,16 +235,36 @@ public interface IBaselineResolver
|
||||
* `offline kit import <tar>` — upload the kit to on‑prem services (Concelier/Excititor).
|
||||
* `offline kit status` — list current seed versions.
|
||||
|
||||
### 2.8 Utilities
|
||||
|
||||
* `config set/get` — endpoint & defaults.
|
||||
* `whoami` — short auth display.
|
||||
* `version` — CLI + protocol versions; release channel.
|
||||
* `tools policy-dsl-validate <paths...> [--strict] [--json]`
|
||||
* `tools policy-schema-export [--output <dir>] [--repo-root <path>]`
|
||||
* `tools policy-simulation-smoke [--scenario-root <path>] [--output <dir>] [--repo-root <path>] [--fixed-time <ISO-8601>]`
|
||||
|
||||
### 2.9 Aggregation-only guard helpers
|
||||
### 2.8 Utilities
|
||||
|
||||
* `config set/get` — endpoint & defaults.
|
||||
* `whoami` — short auth display.
|
||||
* `version` — CLI + protocol versions; release channel.
|
||||
* `tools policy-dsl-validate <paths...> [--strict] [--json]`
|
||||
* `tools policy-schema-export [--output <dir>] [--repo-root <path>]`
|
||||
* `tools policy-simulation-smoke [--scenario-root <path>] [--output <dir>] [--repo-root <path>] [--fixed-time <ISO-8601>]`
|
||||
|
||||
### 2.8.1 User locale preference commands
|
||||
|
||||
* `tenants locale list [--tenant <id>] [--json]`
|
||||
|
||||
* Fetches tenant-visible locale catalog from Platform `GET /api/v1/platform/localization/locales`.
|
||||
* Provides the canonical locale set used by both CLI and UI selection controls.
|
||||
* Supports deterministic text output or JSON payload (`locales`, `count`) for automation.
|
||||
|
||||
* `tenants locale get [--tenant <id>] [--json]`
|
||||
|
||||
* Fetches the authenticated actor's persisted locale preference from Platform `GET /api/v1/platform/preferences/language`.
|
||||
* Resolves tenant context from `--tenant`, then `STELLAOPS_TENANT`, then active tenant profile.
|
||||
* Prints deterministic text output by default (`tenant`, `locale`, `updated`) and optional JSON payload for automation.
|
||||
|
||||
* `tenants locale set <locale> [--tenant <id>] [--json]`
|
||||
|
||||
* Writes the authenticated actor's persisted locale preference through Platform `PUT /api/v1/platform/preferences/language`.
|
||||
* Supported locale set is service-validated (`en-US`, `de-DE`, `bg-BG`, `ru-RU`, `es-ES`, `fr-FR`, `uk-UA`, `zh-TW`, `zh-CN`); CLI pre-validates against the platform locale catalog when available.
|
||||
* This command shares the same preference record consumed by the Web shell locale selector so locale choice follows the user across Web and CLI sessions.
|
||||
|
||||
### 2.9 Aggregation-only guard helpers
|
||||
|
||||
* `sources ingest --dry-run --source <id> --input <path|uri> [--tenant ... --format table|json --output file]`
|
||||
|
||||
|
||||
@@ -59,11 +59,18 @@ The edge metadata system provides explainability for graph relationships:
|
||||
|
||||
- **EdgeReason** enum: `Unknown`, `SbomDependency`, `StaticSymbol`, `RuntimeTrace`, `PackageManifest`, `Lockfile`, `BuildArtifact`, `ImageLayer`, `AdvisoryAffects`, `VexStatement`, `PolicyOverlay`, `AttestationRef`, `OperatorAnnotation`, `TransitiveInference`, `Provenance`.
|
||||
- **EdgeVia** record: Describes how the edge was discovered (method, version, timestamp, confidence in basis points, evidence reference).
|
||||
- **EdgeExplanationPayload** record: Full explanation including reason, via, human-readable summary, evidence list, provenance reference, and tags.
|
||||
- **EdgeProvenanceRef** record: Source system, collection timestamp, SBOM digest, scan digest, attestation ID, event offset.
|
||||
- **EdgeTileWithMetadata** record: Extends `EdgeTile` with `Explanation` property containing the full metadata.
|
||||
|
||||
## 4) Storage considerations
|
||||
- **EdgeExplanationPayload** record: Full explanation including reason, via, human-readable summary, evidence list, provenance reference, and tags.
|
||||
- **EdgeProvenanceRef** record: Source system, collection timestamp, SBOM digest, scan digest, attestation ID, event offset.
|
||||
- **EdgeTileWithMetadata** record: Extends `EdgeTile` with `Explanation` property containing the full metadata.
|
||||
|
||||
### 3.3) Localization runtime contract (Sprint 20260224_002)
|
||||
|
||||
- Graph API now initializes localization via `AddStellaOpsLocalization(...)`, `AddTranslationBundle(...)`, `AddRemoteTranslationBundles()`, `UseStellaOpsLocalization()`, and `LoadTranslationsAsync()`.
|
||||
- Locale resolution order for API messages is deterministic: `X-Locale` header -> `Accept-Language` header -> default locale (`en-US`).
|
||||
- Translation layering is deterministic: shared embedded `common` bundle -> Graph embedded bundle (`Translations/*.graph.json`) -> Platform runtime override bundle.
|
||||
- This rollout localizes selected error paths (for example, edge/export not found, invalid reason, and tenant/auth validation text) for `en-US` and `de-DE`.
|
||||
|
||||
## 4) Storage considerations
|
||||
|
||||
- Backed by either:
|
||||
- **Relational + adjacency** (PostgreSQL tables `graph_nodes`, `graph_edges`, `graph_overlays`) with deterministic ordering and streaming exports.
|
||||
|
||||
@@ -13,6 +13,7 @@ Provide a single, deterministic aggregation layer for cross-service UX workflows
|
||||
- Aggregate quota usage across Authority, Gateway, Orchestrator, and storage backends.
|
||||
- Persist onboarding progress and tenant setup milestones.
|
||||
- Persist dashboard personalization and layout preferences.
|
||||
- Persist authenticated user language preference for shared Web/CLI locale selection.
|
||||
- Provide global search aggregation across entities.
|
||||
- Provide global context selectors (region/environment/time window) and per-user persistence for Pack 22 top-bar context.
|
||||
- Provide Pack 22 release read-model projections for list/detail/activity/approvals queue views.
|
||||
@@ -43,6 +44,8 @@ Provide a single, deterministic aggregation layer for cross-service UX workflows
|
||||
### Preferences
|
||||
- GET `/api/v1/platform/preferences/dashboard`
|
||||
- PUT `/api/v1/platform/preferences/dashboard`
|
||||
- GET `/api/v1/platform/preferences/language`
|
||||
- PUT `/api/v1/platform/preferences/language`
|
||||
- GET `/api/v1/platform/dashboard/profiles`
|
||||
- GET `/api/v1/platform/dashboard/profiles/{profileId}`
|
||||
- POST `/api/v1/platform/dashboard/profiles`
|
||||
@@ -50,11 +53,24 @@ Provide a single, deterministic aggregation layer for cross-service UX workflows
|
||||
### Global search
|
||||
- GET `/api/v1/search` (alias to `/api/v1/platform/search`)
|
||||
- GET `/api/v1/platform/search`
|
||||
- Legacy notice: both endpoints now emit deprecation metadata (`Deprecation`, `Sunset`, `Link`, `Warning`) and are being replaced by Unified Search `POST /api/v1/search/query`.
|
||||
|
||||
### Metadata
|
||||
- GET `/api/v1/platform/metadata`
|
||||
- Response includes a capabilities list for UI bootstrapping; analytics capability is reported only when analytics storage is configured.
|
||||
|
||||
### Localization
|
||||
- GET `/platform/i18n/{locale}.json` (anonymous, cacheable UI translation bundle)
|
||||
- GET `/api/v1/platform/localization/bundles/{locale}`
|
||||
- GET `/api/v1/platform/localization/bundles/{locale}/{namespace}`
|
||||
- GET `/api/v1/platform/localization/locales` (catalog used by Web and CLI locale selectors)
|
||||
- PUT `/api/v1/platform/localization/bundles`
|
||||
- DELETE `/api/v1/platform/localization/strings/{locale}/{key}`
|
||||
- Backend locale resolution contract: `X-Locale` -> `Accept-Language` -> default locale.
|
||||
- Runtime bundle layering consumed by backend services: shared embedded `common` -> service embedded bundle -> Platform override bundle.
|
||||
- Platform ships locale-complete `ui` and `platform` namespace bundles for `en-US`, `de-DE`, `bg-BG`, `ru-RU`, `es-ES`, `fr-FR`, `uk-UA`, `zh-TW`, `zh-CN`; shared localization library now provides `common` bundles for the same locale set.
|
||||
- Bundled locales currently shipped: `en-US`, `de-DE`, `bg-BG`, `ru-RU`, `es-ES`, `fr-FR`, `uk-UA`, `zh-TW`, `zh-CN`.
|
||||
|
||||
## API surface (v2)
|
||||
|
||||
### Global context
|
||||
@@ -108,11 +124,12 @@ Provide a single, deterministic aggregation layer for cross-service UX workflows
|
||||
- Alias usage telemetry is emitted as deterministic event keys (`alias_<method>_<route_pattern>`) with tenant hash metadata only.
|
||||
|
||||
## Data model
|
||||
- `platform.dashboard_preferences` (dashboard layout, widgets, filters)
|
||||
- `platform.dashboard_preferences` (dashboard layout, widgets, filters, optional user `locale` preference key)
|
||||
- `platform.dashboard_profiles` (saved profiles per tenant)
|
||||
- `platform.onboarding_state` (step state, timestamps, actor)
|
||||
- `platform.quota_alerts` (per-tenant quota alert thresholds)
|
||||
- `platform.search_history` (optional, user-scoped, append-only)
|
||||
- `platform.translations` (tenant + locale scoped translation override store)
|
||||
- `platform.context_regions` (global region selector inventory)
|
||||
- `platform.context_environments` (global environment selector inventory with region linkage)
|
||||
- `platform.ui_context_preferences` (tenant + actor scoped region/environment/time-window selections)
|
||||
|
||||
@@ -31,6 +31,13 @@ The service operates strictly downstream of the **Aggregation-Only Contract (AOC
|
||||
|
||||
Non-goals: policy authoring UI (handled by Console), ingestion or advisory normalisation (Concelier), VEX consensus (Excititor), runtime enforcement (Zastava).
|
||||
|
||||
### 1.1 · Localization runtime contract (Sprint 20260224_002)
|
||||
|
||||
- Policy Gateway now initializes StellaOps localization with `AddStellaOpsLocalization(...)`, `AddTranslationBundle(...)`, `AddRemoteTranslationBundles()`, `UseStellaOpsLocalization()`, and `LoadTranslationsAsync()`.
|
||||
- Locale resolution order for request-facing strings is deterministic: `X-Locale` header -> `Accept-Language` header -> default locale (`en-US`).
|
||||
- Translation sources are layered deterministically: shared embedded `common` bundle -> Policy embedded bundle (`Translations/*.policy.json`) -> Platform runtime override bundle.
|
||||
- The rollout localizes selected request validation and readiness responses for `en-US` and `de-DE`.
|
||||
|
||||
---
|
||||
|
||||
## 2 · High-Level Architecture
|
||||
|
||||
@@ -222,9 +222,16 @@ POST /reports { imageDigest, policyRevision? } → { r
|
||||
GET /catalog/artifacts/{id} → { meta }
|
||||
GET /healthz | /readyz | /metrics
|
||||
```
|
||||
See docs/modules/scanner/byos-ingestion.md for BYOS workflow, formats, and troubleshooting.
|
||||
|
||||
### Report events
|
||||
See docs/modules/scanner/byos-ingestion.md for BYOS workflow, formats, and troubleshooting.
|
||||
|
||||
### 4.1 Localization runtime contract (Sprint 20260224_002)
|
||||
|
||||
- Scanner.WebService initializes localization via `AddStellaOpsLocalization(...)`, `AddTranslationBundle(...)`, `AddRemoteTranslationBundles()`, `UseStellaOpsLocalization()`, and `LoadTranslationsAsync()`.
|
||||
- Locale resolution order is deterministic: `X-Locale` header -> `Accept-Language` header -> configured default locale (`en-US`).
|
||||
- Translation source layering is deterministic: embedded shared `common` bundle (library) -> embedded Scanner bundle (`Translations/*.scanner.json`) -> Platform runtime overrides fetched through the remote provider.
|
||||
- Current localized API responses in this rollout are provided for `en-US` and `de-DE` (for example, slice query validation and not-found responses).
|
||||
|
||||
### Report events
|
||||
|
||||
When `scanner.events.enabled = true`, the WebService serialises the signed report (canonical JSON + DSSE envelope) with `NotifyCanonicalJsonSerializer` and publishes two Redis Stream entries (`scanner.report.ready`, `scanner.scan.completed`) to the configured stream (default `stella.events`). The stream fields carry the whole envelope plus lightweight headers (`kind`, `tenant`, `ts`) so Notify and UI timelines can consume the event bus without recomputing signatures. Publish timeouts and bounded stream length are controlled via `scanner:events:publishTimeoutSeconds` and `scanner:events:maxStreamLength`. If the queue driver is already Redis and no explicit events DSN is provided, the host reuses the queue connection and auto-enables event emission so deployments get live envelopes without extra wiring. Compose/Helm bundles expose the same knobs via the `SCANNER__EVENTS__*` environment variables for quick tuning.
|
||||
|
||||
|
||||
@@ -301,8 +301,8 @@ export interface NotifyDelivery {
|
||||
## 9) Accessibility, i18n & theming
|
||||
|
||||
* **A11y**: WCAG 2.2 AA; keyboard navigation, focus management, ARIA roles; color‑contrast tokens verified by unit tests.
|
||||
* **I18n**: Angular i18n + runtime translation loader (`/locales/{lang}.json`); dates/numbers localized via `Intl`.
|
||||
* **Languages**: English default; Bulgarian, German, Japanese as initial additions.
|
||||
* **I18n**: runtime translation loader from Platform (`/platform/i18n/{locale}.json`) with embedded offline fallback bundles (`en-US`, `de-DE`, `bg-BG`, `ru-RU`, `es-ES`, `fr-FR`, `uk-UA`, `zh-TW`, `zh-CN`); locale selectors in topbar and `/settings/language` use Platform locale catalog (`GET /api/v1/platform/localization/locales`) with local fallback when catalog lookup is unavailable; fallback selection prefers the requested locale family first, then `en-US`; dates/numbers localized via `Intl`. Authenticated locale changes from both topbar selector and dedicated settings route (`/settings/language`) are written to Platform user preferences (`GET/PUT /api/v1/platform/preferences/language`) so preference is shared across Web and CLI sessions, with localStorage used as offline fallback.
|
||||
* **Languages**: English default; German, Bulgarian, Russian, Spanish, French, Ukrainian, Chinese (Traditional), Chinese (Simplified).
|
||||
* **Theming**: dark/light via CSS variables; persisted in `prefers-color-scheme` aware store.
|
||||
* **Branding**: tenant-scoped theme tokens and logo pulled from Authority `/console/branding` after login.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user