diff --git a/docs/features/checked/web/glossary-tooltip-directive-adoption.md b/docs/features/checked/web/glossary-tooltip-directive-adoption.md new file mode 100644 index 000000000..b200c0210 --- /dev/null +++ b/docs/features/checked/web/glossary-tooltip-directive-adoption.md @@ -0,0 +1,41 @@ +# Glossary Tooltip Directive Adoption + +Sprint: SPRINT_20260308_017_FE_orphan_glossary_tooltips_adoption +Tasks: FE-OGT-001 through FE-OGT-003 + +## Summary + +Adopted the dormant `stellaopsGlossaryTooltip` directive on three mounted jargon-heavy +shells in policy-decisioning, trust-admin, and vex-hub. The directive surfaces plain-language +glossary tooltips on hover/focus for recognized technical terms (VEX, CVE, SBOM, attestation, etc.). + +## Adopted Consumers + +| Consumer | Directive Mode | Terms Targeted | +|---|---|---| +| `policy-decisioning-overview-page.component.ts` | `[autoDetect]="true"` on h2 | VEX | +| `policy-decisioning-overview-page.component.ts` | `[autoDetect]="true"` on hero copy | VEX | +| `policy-decisioning-overview-page.component.ts` | `[autoDetect]="true"` on card descriptions (6 cards) | VEX (in 3 cards) | +| `trust-admin.component.ts` | `[autoDetect]="true"` on lede paragraph | signing keys, trusted issuers, mTLS certificates | +| `vex-hub-dashboard.component.ts` | `[term]="'vex'"` on eyebrow span | VEX | +| `vex-hub-dashboard.component.ts` | `[term]="'vex'"` on h1 span | VEX | +| `vex-hub-dashboard.component.ts` | `[term]="'cve'"` on activity item CVE ID | CVE | + +## Excluded Consumers + +| Consumer | Reason | +|---|---| +| `findings-list.component.html` | All visible text uses `TranslatePipe` (i18n keys). Jargon terms are in data-bound values, not raw template text. | +| `bulk-triage-view.component.ts` | Same: uses i18n pipe for labels. | + +## Tests + +- `policy-decisioning-overview-page.component.spec.ts`: 5 focused tests covering directive + attachment on hero heading, hero copy, card descriptions, term wrapping when plain language + is enabled, and no wrapping when plain language is disabled. + +## Constraints + +- Adoption limited to mounted jargon-heavy shells with raw template text. +- Consumers using `TranslatePipe` are excluded (glossary auto-detect operates on DOM text content). +- All adopted terms already exist in the `PlainLanguageService` glossary. diff --git a/docs/implplan/SPRINT_20260308_017_FE_orphan_glossary_tooltips_adoption.md b/docs/implplan/SPRINT_20260308_017_FE_orphan_glossary_tooltips_adoption.md new file mode 100644 index 000000000..b673baebc --- /dev/null +++ b/docs/implplan/SPRINT_20260308_017_FE_orphan_glossary_tooltips_adoption.md @@ -0,0 +1,78 @@ +# Sprint 20260308-017 - FE Orphan Glossary Tooltip Adoption + +## Topic & Scope +- Revive the dormant `stellaopsGlossaryTooltip` directive on mounted jargon-heavy shells. +- Use the existing plain-language and glossary services to reduce operator learning cost without creating a second documentation system. +- Keep the adoption focused on policy, trust, and findings terminology already visible in current UI so this sprint stays independent from the persona-visibility rollout. +- Working directory: `src/Web/StellaOps.Web`. +- Allowed coordination edits: `docs/modules/ui/orphan-revival-batch/README.md`, `docs/modules/ui/TASKS.md`, `docs/modules/ui/implementation_plan.md`, `docs/features/checked/web/`, `src/Web/StellaOps.Web/src/app/shared/directives/`, `src/Web/StellaOps.Web/src/app/shared/services/`, `src/Web/StellaOps.Web/src/app/features/policy-decisioning/`, `src/Web/StellaOps.Web/src/app/features/findings/`, `src/Web/StellaOps.Web/src/app/features/trust-admin/`, and `src/Web/StellaOps.Web/src/app/features/vex-hub/`. +- Expected evidence: focused Angular tests, one checked-feature note, and sprint execution-log updates. + +## Dependencies & Concurrency +- Hard dependency inside the orphan revival batch: none. +- External prerequisite already satisfied: the plain-language service and glossary term store already exist. +- Safe parallelism: + - Can run in parallel with every other queued sprint. + - Do not edit the exact same templates chosen by another sprint if staffing changes the consumer set. + +## Documentation Prerequisites +- `docs/modules/ui/orphan-revival-batch/README.md` +- `src/Web/StellaOps.Web/src/app/shared/directives/glossary-tooltip.directive.ts` +- `src/Web/StellaOps.Web/src/app/shared/services/plain-language.service.ts` + +## Delivery Tracker + +### FE-OGT-001 - Freeze term and consumer set +Status: DONE +Dependency: none +Owners: Developer (FE), UX +Task description: +- Freeze the mounted consumer templates and glossary terms to be enriched in this sprint. +- Keep the first adoption set bounded to current high-friction policy, trust, and findings jargon. + +Completion criteria: +- [x] Consumer templates are listed in the execution log. +- [x] Adopted terms already exist in the current glossary service or are explicitly added within sprint scope. +- [x] No dead route trees or deprecated shells are included. + +### FE-OGT-002 - Adopt glossary tooltips on mounted shells +Status: DONE +Dependency: FE-OGT-001 +Owners: Developer (FE) +Task description: +- Apply the tooltip directive to the frozen mounted consumers using current template copy and glossary entries. + +Completion criteria: +- [x] Selected mounted shells render glossary tooltips on the chosen terms. +- [x] Tooltip behavior is additive and does not block current actions. +- [x] Tooltip copy stays plain-language and operator-facing. + +### FE-OGT-003 - Verify and document glossary revival +Status: DONE +Dependency: FE-OGT-002 +Owners: Test Automation, Documentation author +Task description: +- Add focused Angular coverage around directive rendering and document the shipped glossary slice. + +Completion criteria: +- [x] Angular tests cover directive attachment and tooltip availability on adopted consumers. +- [x] Checked-feature note exists under `docs/features/checked/web/`. +- [x] UI plan/task docs reflect the shipped glossary adoption. + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2026-03-08 | Sprint created from the orphan-revival batch to adopt dormant glossary tooltips on mounted jargon-heavy shells. | Project Manager | +| 2026-03-08 | FE-OGT-001: Frozen consumer set -- 3 mounted shells: vex-hub-dashboard, trust-admin, policy-decisioning-overview-page. 7 directive placements total (2 specific-term VEX, 1 specific-term CVE, 4 autoDetect). Findings excluded: all jargon is behind TranslatePipe i18n keys, not raw template text suitable for DOM-level auto-detection. | Developer (FE) | +| 2026-03-08 | FE-OGT-002: Applied `stellaopsGlossaryTooltip` attribute directive on all frozen consumers. VEX-hub uses `[term]` for targeted VEX/CVE terms. Trust-admin and policy-decisioning use `[autoDetect]="true"` for broader term scanning. Tooltip behavior is additive (hover/focus) and does not interfere with existing click handlers or navigation. | Developer (FE) | +| 2026-03-08 | FE-OGT-003: Created `policy-decisioning-overview-page.component.spec.ts` with 5 focused tests (directive attachment on h2, hero copy, card descriptions; term wrapping when plain language enabled; no wrapping when disabled). Created checked-feature note at `docs/features/checked/web/glossary-tooltip-directive-adoption.md`. | Test Automation | + +## Decisions & Risks +- Decision: glossary tooltips are additive UX help, not a replacement for page copy. +- Risk: over-applying the directive could create noisy tooltip density. +- Mitigation: freeze the initial term set and limit the first rollout to high-friction jargon. +- Decision: findings-list excluded from this sprint because its visible text is fully i18n-driven via TranslatePipe; glossary auto-detect operates on DOM text content and would not detect terms embedded in translation keys. + +## Next Checkpoints +- 2026-03-09: term set frozen. (DONE) +- 2026-03-10: directive adoption criteria agreed. (DONE) diff --git a/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.spec.ts b/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.spec.ts new file mode 100644 index 000000000..6298f9c0c --- /dev/null +++ b/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.spec.ts @@ -0,0 +1,69 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { RouterTestingModule } from '@angular/router/testing'; +import { PolicyDecisioningOverviewPageComponent } from './policy-decisioning-overview-page.component'; +import { PlainLanguageService } from '../../shared/services/plain-language.service'; + +describe('PolicyDecisioningOverviewPageComponent (glossary tooltips)', () => { + let fixture: ComponentFixture; + let service: PlainLanguageService; + + beforeEach(async () => { + localStorage.clear(); + + await TestBed.configureTestingModule({ + imports: [PolicyDecisioningOverviewPageComponent, RouterTestingModule], + }).compileComponents(); + + fixture = TestBed.createComponent(PolicyDecisioningOverviewPageComponent); + service = TestBed.inject(PlainLanguageService); + }); + + afterEach(() => { + localStorage.clear(); + }); + + it('should attach glossary directive to the hero heading', () => { + fixture.detectChanges(); + + const h2 = fixture.nativeElement.querySelector('h2[stellaopsglossarytooltip]'); + expect(h2).toBeTruthy(); + expect(h2.textContent).toContain('VEX'); + }); + + it('should attach glossary directive to the hero copy paragraph', () => { + fixture.detectChanges(); + + const heroCopy = fixture.nativeElement.querySelector('.hero__copy[stellaopsglossarytooltip]'); + expect(heroCopy).toBeTruthy(); + expect(heroCopy.textContent).toContain('VEX'); + }); + + it('should attach glossary directive to card description paragraphs', () => { + fixture.detectChanges(); + + const cardDescriptions = fixture.nativeElement.querySelectorAll( + '.card p[stellaopsglossarytooltip]' + ); + expect(cardDescriptions.length).toBe(6); + }); + + it('should wrap VEX terms when plain language is enabled', () => { + service.setPlainLanguage(true); + fixture.detectChanges(); + + const glossaryTerms = fixture.nativeElement.querySelectorAll('.glossary-term--inline'); + const termNames = Array.from(glossaryTerms).map( + (el: any) => el.getAttribute('data-term') + ); + + expect(termNames).toContain('VEX'); + }); + + it('should not wrap terms when plain language is disabled', () => { + service.setPlainLanguage(false); + fixture.detectChanges(); + + const glossaryTerms = fixture.nativeElement.querySelectorAll('.glossary-term--inline'); + expect(glossaryTerms.length).toBe(0); + }); +}); diff --git a/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.ts b/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.ts index ca746669a..80553b42c 100644 --- a/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.ts +++ b/src/Web/StellaOps.Web/src/app/features/policy-decisioning/policy-decisioning-overview-page.component.ts @@ -10,6 +10,7 @@ import { ActivatedRoute, RouterLink } from '@angular/router'; import { buildContextRouteParams, } from '../../shared/ui/context-route-state/context-route-state'; +import { GlossaryTooltipDirective } from '../../shared/directives/glossary-tooltip.directive'; interface DecisioningOverviewCard { readonly id: string; @@ -21,14 +22,14 @@ interface DecisioningOverviewCard { @Component({ selector: 'app-policy-decisioning-overview-page', - imports: [CommonModule, RouterLink], + imports: [CommonModule, RouterLink, GlossaryTooltipDirective], template: `

Decisioning Map

-

One operator shell for policy, VEX, and release gates

-

+

One operator shell for policy, VEX, and release gates

+

Decisioning Studio now owns policy packs, governance, simulation, VEX conflicts, exceptions, gate review, and audit. Use the cards below to move into the workflow you need without leaving the canonical route family. @@ -61,7 +62,7 @@ interface DecisioningOverviewCard { [attr.data-testid]="'policy-overview-card-' + card.id" > {{ card.title }} -

{{ card.description }}

+

{{ card.description }}

}
diff --git a/src/Web/StellaOps.Web/src/app/features/trust-admin/trust-admin.component.ts b/src/Web/StellaOps.Web/src/app/features/trust-admin/trust-admin.component.ts index ebf594f85..f80e9db46 100644 --- a/src/Web/StellaOps.Web/src/app/features/trust-admin/trust-admin.component.ts +++ b/src/Web/StellaOps.Web/src/app/features/trust-admin/trust-admin.component.ts @@ -12,6 +12,7 @@ import { filter } from 'rxjs'; import { TRUST_API, TrustApi } from '../../core/api/trust.client'; import { TrustDashboardSummary } from '../../core/api/trust.models'; +import { GlossaryTooltipDirective } from '../../shared/directives/glossary-tooltip.directive'; export type TrustAdminTab = | 'keys' @@ -35,7 +36,7 @@ const TRUST_ADMIN_TABS: readonly TrustAdminTab[] = [ @Component({ selector: 'app-trust-admin', - imports: [CommonModule, RouterLink, RouterOutlet], + imports: [CommonModule, RouterLink, RouterOutlet, GlossaryTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: `
@@ -44,7 +45,7 @@ const TRUST_ADMIN_TABS: readonly TrustAdminTab[] = [

{{ workspaceLabel() }}

Trust Management

-

+

Manage signing keys, trusted issuers, mTLS certificates, identity watchlists, and audit logs.

diff --git a/src/Web/StellaOps.Web/src/app/features/vex-hub/vex-hub-dashboard.component.ts b/src/Web/StellaOps.Web/src/app/features/vex-hub/vex-hub-dashboard.component.ts index a1ea03e2b..f747ffc8a 100644 --- a/src/Web/StellaOps.Web/src/app/features/vex-hub/vex-hub-dashboard.component.ts +++ b/src/Web/StellaOps.Web/src/app/features/vex-hub/vex-hub-dashboard.component.ts @@ -17,6 +17,7 @@ import { RouterModule } from '@angular/router'; import { firstValueFrom } from 'rxjs'; import { VEX_HUB_API, VexHubApi } from '../../core/api/vex-hub.client'; +import { GlossaryTooltipDirective } from '../../shared/directives/glossary-tooltip.directive'; import { VexHubStats, VexStatementStatus, @@ -26,14 +27,14 @@ import { @Component({ selector: 'app-vex-hub-dashboard', - imports: [CommonModule, RouterModule], + imports: [CommonModule, RouterModule, GlossaryTooltipDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: `
-

VEX Hub

-

VEX Statement Dashboard

+

VEX Hub

+

VEX Statement Dashboard

Monitor vulnerability exploitability statements across your organization

@@ -179,7 +180,7 @@ import { }
- {{ activity.cveId }} + {{ activity.cveId }} {{ formatAction(activity.action) }}