chore(web): prune dead ui cleanup artifacts

This commit is contained in:
master
2026-03-08 21:59:38 +02:00
parent f40043ed50
commit aa7e0e937c
66 changed files with 676 additions and 66053 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 KiB

View File

@@ -1,101 +0,0 @@
const { chromium } = require('playwright');
const session = {
subjectId: 'user-author',
tenant: 'tenant-default',
scopes: [
'ui.read',
'policy:read',
'policy:author',
'policy:simulate',
'advisory-ai:view',
'advisory-ai:operate',
'findings:read',
'vex:read',
'admin',
],
};
(async () => {
const browser = await chromium.launch({
headless: true,
args: ['--no-sandbox', '--no-proxy-server'],
});
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
const navHistory = [];
const httpErrors = [];
const failures = [];
let currentUrl = '';
page.on('framenavigated', (frame) => {
if (frame !== page.mainFrame()) {
return;
}
const entry = `${new Date().toISOString()} ${frame.url()}`;
navHistory.push(entry);
console.log('[nav]', entry);
});
page.on('response', (response) => {
if (response.status() < 400) {
return;
}
const request = response.request();
const entry = `${response.status()} ${request.method()} ${response.url()}`;
httpErrors.push(entry);
console.log('[http-error]', entry);
});
page.on('requestfailed', (request) => {
const entry = `${request.method()} ${request.url()} :: ${request.failure()?.errorText ?? 'failed'}`;
failures.push(entry);
console.log('[requestfailed]', entry);
});
page.on('console', (msg) => {
if (msg.type() === 'error') {
console.log('[console-error]', msg.text());
}
});
await page.addInitScript((stubSession) => {
window.__stellaopsTestSession = stubSession;
}, session);
const target = process.argv[2] ?? 'https://stella-ops.local/';
console.log('[goto]', target);
try {
await page.goto(target, { waitUntil: 'commit', timeout: 20000 });
} catch (error) {
console.log('[goto-error]', error.message);
}
for (let i = 0; i < 20; i += 1) {
const url = page.url();
if (url !== currentUrl) {
currentUrl = url;
console.log('[url-change]', url);
}
await page.waitForTimeout(1000);
}
const searchInputCount = await page
.evaluate(() => document.querySelectorAll('app-global-search input[type="text"]').length)
.catch(() => -1);
console.log('[final-url]', page.url());
console.log('[title]', await page.title().catch(() => '<title unavailable>'));
console.log('[search-input-count]', searchInputCount);
console.log('[nav-count]', navHistory.length);
console.log('[http-error-count]', httpErrors.length);
console.log('[failed-request-count]', failures.length);
await page.screenshot({ path: 'output/playwright/stella-ops-local-load-check-viewport.png' });
await browser.close();
})();

View File

@@ -1,66 +0,0 @@
const { chromium } = require('playwright');
const session = {
subjectId: 'user-author',
tenant: 'tenant-default',
scopes: ['ui.read', 'policy:read', 'policy:author', 'policy:simulate', 'advisory:search', 'advisory:read', 'search:read', 'findings:read', 'vex:read', 'admin'],
};
(async () => {
const browser = await chromium.launch({ headless: true, args: ['--no-sandbox'] });
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
page.on('requestfailed', (request) => {
const url = request.url();
if (url.includes('/search')) {
console.log('[requestfailed]', request.method(), url, request.failure()?.errorText);
}
});
page.on('response', (response) => {
const url = response.url();
if (
url.includes('/api/v1/search/query') ||
url.includes('/api/v1/advisory-ai/search') ||
url.includes('/api/v1/advisory-ai/search/analytics')
) {
const req = response.request();
console.log('[response]', req.method(), response.status(), url);
}
});
await page.addInitScript((stubSession) => {
window.__stellaopsTestSession = stubSession;
}, session);
const url = process.argv[2] || 'https://stella-ops.local/';
console.log('[goto]', url);
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForTimeout(2000);
const count = await page.evaluate(() => document.querySelectorAll('app-global-search input[type="text"]').length);
console.log('[search-input-count]', count);
if (count === 0) {
console.log('[page-url]', page.url());
console.log('[title]', await page.title());
await page.screenshot({ path: 'output/playwright/header-search-repro-no-input.png', fullPage: true });
await browser.close();
process.exit(1);
}
await page.click('app-global-search input[type="text"]', { timeout: 15000 });
await page.fill('app-global-search input[type="text"]', 'critical findings', { timeout: 15000 });
await page.waitForTimeout(3000);
const results = await page.evaluate(() => document.querySelectorAll('app-entity-card').length);
const emptyText = await page.locator('.search__empty').allTextContents();
const degradedVisible = await page.locator('.search__degraded-banner').isVisible().catch(() => false);
console.log('[entity-cards]', results);
console.log('[empty-text]', emptyText.join(' | '));
console.log('[degraded-banner]', degradedVisible);
await page.screenshot({ path: 'output/playwright/header-search-repro-live.png', fullPage: true });
await browser.close();
})();

View File

@@ -1,66 +0,0 @@
const { chromium } = require('playwright');
const session = {
subjectId: 'user-author',
tenant: 'tenant-default',
scopes: ['ui.read','policy:read','policy:author','policy:simulate','advisory:search','advisory:read','search:read','findings:read','vex:read','admin']
};
(async () => {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
page.on('requestfailed', (request) => {
const url = request.url();
if (url.includes('/search')) {
console.log('[requestfailed]', request.method(), url, request.failure()?.errorText);
}
});
page.on('response', (response) => {
const url = response.url();
if (
url.includes('/api/v1/search/query') ||
url.includes('/api/v1/advisory-ai/search') ||
url.includes('/api/v1/advisory-ai/search/analytics')
) {
const req = response.request();
console.log('[response]', req.method(), response.status(), url);
}
});
await page.addInitScript((stubSession) => {
window.__stellaopsTestSession = stubSession;
}, session);
const url = process.argv[2] || 'https://stella-ops.local:10000/';
console.log('[goto]', url);
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
await page.waitForTimeout(2000);
const count = await page.evaluate(() => document.querySelectorAll('app-global-search input[type="text"]').length);
console.log('[search-input-count]', count);
if (count === 0) {
console.log('[page-url]', page.url());
console.log('[title]', await page.title());
await page.screenshot({ path: 'output/playwright/header-search-repro-no-input.png', fullPage: true });
await browser.close();
process.exit(1);
}
await page.click('app-global-search input[type="text"]', { timeout: 15000 });
await page.fill('app-global-search input[type="text"]', 'critical findings', { timeout: 15000 });
await page.waitForTimeout(3000);
const results = await page.evaluate(() => document.querySelectorAll('app-entity-card').length);
const emptyText = await page.locator('.search__empty').allTextContents();
const degradedVisible = await page.locator('.search__degraded-banner').isVisible().catch(() => false);
console.log('[entity-cards]', results);
console.log('[empty-text]', emptyText.join(' | '));
console.log('[degraded-banner]', degradedVisible);
await page.screenshot({ path: 'output/playwright/header-search-repro.png', fullPage: true });
await browser.close();
})();

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -1,82 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-release-control-governance-hub',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="governance-hub">
<header class="header">
<h1>Governance</h1>
<p>Policy and exception controls anchored under Release Control.</p>
</header>
<div class="cards">
<a routerLink="/ops/policy/baselines" class="card">
<h2>Policy Baselines</h2>
<p>Environment-scoped baseline definitions and lock rules.</p>
</a>
<a routerLink="/ops/policy/gates" class="card">
<h2>Governance Rules</h2>
<p>Rule catalog for release control gate enforcement.</p>
</a>
<a routerLink="/ops/policy/simulation" class="card">
<h2>Policy Simulation</h2>
<p>Dry-run policy evaluations before production rollout.</p>
</a>
<a routerLink="/ops/policy/waivers" class="card">
<h2>Exception Workflow</h2>
<p>Exception requests, approvals, and expiry management.</p>
</a>
</div>
</section>
`,
styles: [
`
.governance-hub {
display: grid;
gap: 0.8rem;
}
.header h1 {
margin: 0 0 0.2rem;
font-size: 1.4rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary);
font-size: 0.84rem;
}
.cards {
display: grid;
gap: 0.7rem;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.card {
border: 1px solid var(--color-border-primary);
border-radius: var(--radius-md);
background: var(--color-surface-primary);
padding: 0.72rem 0.8rem;
text-decoration: none;
color: inherit;
}
.card h2 {
margin: 0 0 0.25rem;
font-size: 0.95rem;
}
.card p {
margin: 0;
font-size: 0.8rem;
color: var(--color-text-secondary);
}
`,
],
})
export class ReleaseControlGovernanceHubComponent {}

View File

@@ -1,59 +0,0 @@
import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
@Component({
selector: 'app-release-control-governance-section',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="governance-section">
<header>
<h1>{{ sectionTitle() }}</h1>
<p>This governance area is scaffolded and ready for backend contract binding.</p>
</header>
<p class="note">Canonical location: Release Control &gt; Governance.</p>
<a routerLink="/ops/policy">Back to Governance Hub</a>
</section>
`,
styles: [
`
.governance-section {
display: grid;
gap: 0.7rem;
}
h1 {
margin: 0 0 0.2rem;
font-size: 1.35rem;
}
p {
margin: 0;
font-size: 0.82rem;
color: var(--color-text-secondary);
}
.note {
border: 1px solid var(--color-border-primary);
border-radius: var(--radius-md);
background: var(--color-surface-primary);
padding: 0.55rem 0.65rem;
}
a {
color: var(--color-brand-primary);
text-decoration: none;
font-size: 0.82rem;
}
`,
],
})
export class ReleaseControlGovernanceSectionComponent {
private readonly route = inject(ActivatedRoute);
readonly sectionTitle = signal(
(this.route.snapshot.data['sectionTitle'] as string | undefined) ?? 'Governance'
);
}

View File

@@ -1,49 +0,0 @@
import { Routes } from '@angular/router';
export const RELEASE_CONTROL_GOVERNANCE_ROUTES: Routes = [
{
path: '',
title: 'Governance',
data: { breadcrumb: 'Governance' },
loadComponent: () =>
import('./release-control-governance-hub.component').then(
(m) => m.ReleaseControlGovernanceHubComponent
),
},
{
path: 'baselines',
title: 'Policy Baselines',
data: { breadcrumb: 'Policy Baselines', sectionTitle: 'Policy Baselines' },
loadComponent: () =>
import('./release-control-governance-section.component').then(
(m) => m.ReleaseControlGovernanceSectionComponent
),
},
{
path: 'rules',
title: 'Governance Rules',
data: { breadcrumb: 'Governance Rules', sectionTitle: 'Governance Rules' },
loadComponent: () =>
import('./release-control-governance-section.component').then(
(m) => m.ReleaseControlGovernanceSectionComponent
),
},
{
path: 'simulation',
title: 'Policy Simulation',
data: { breadcrumb: 'Policy Simulation', sectionTitle: 'Policy Simulation' },
loadComponent: () =>
import('./release-control-governance-section.component').then(
(m) => m.ReleaseControlGovernanceSectionComponent
),
},
{
path: 'exceptions',
title: 'Exception Workflow',
data: { breadcrumb: 'Exception Workflow', sectionTitle: 'Exception Workflow' },
loadComponent: () =>
import('./release-control-governance-section.component').then(
(m) => m.ReleaseControlGovernanceSectionComponent
),
},
];

View File

@@ -1,129 +0,0 @@
import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';
import { ActivatedRoute, RouterLink } from '@angular/router';
interface EnvironmentNode {
id: string;
stage: string;
status: string;
}
@Component({
selector: 'app-region-detail',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="region-detail">
<header class="header">
<h1>{{ regionLabel() }} Region</h1>
<p>Pipeline posture by environment with promotion flow context.</p>
</header>
<section class="summary">
<article>
<span>Total environments</span>
<strong>{{ environments.length }}</strong>
</article>
<article>
<span>Overall health</span>
<strong>DEGRADED</strong>
</article>
<article>
<span>SBOM posture</span>
<strong>WARN</strong>
</article>
</section>
<section class="pipeline">
@for (env of environments; track env.id) {
<a class="pipeline-node" [routerLink]="['/releases/environments', regionLabel(), 'environments', env.id]">
<h2>{{ env.id }}</h2>
<p>{{ env.stage }}</p>
<p>Status: {{ env.status }}</p>
</a>
}
</section>
</section>
`,
styles: [
`
.region-detail {
display: grid;
gap: 0.9rem;
}
.header h1 {
margin: 0 0 0.2rem;
font-size: 1.42rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary);
font-size: 0.84rem;
}
.summary {
display: grid;
gap: 0.65rem;
grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
.summary article {
border: 1px solid var(--color-border-primary);
border-radius: var(--radius-md);
background: var(--color-surface-primary);
padding: 0.6rem 0.7rem;
}
.summary span {
display: block;
font-size: 0.72rem;
color: var(--color-text-secondary);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.summary strong {
font-size: 1.08rem;
}
.pipeline {
display: grid;
gap: 0.7rem;
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.pipeline-node {
border: 1px solid var(--color-border-primary);
border-radius: var(--radius-md);
background: var(--color-surface-primary);
padding: 0.65rem 0.75rem;
text-decoration: none;
color: inherit;
}
.pipeline-node h2 {
margin: 0 0 0.2rem;
font-size: 0.98rem;
}
.pipeline-node p {
margin: 0.14rem 0;
font-size: 0.8rem;
color: var(--color-text-secondary);
}
`,
],
})
export class RegionDetailComponent {
private readonly route = inject(ActivatedRoute);
readonly regionLabel = signal(this.route.snapshot.paramMap.get('region') ?? 'global');
readonly environments: EnvironmentNode[] = [
{ id: 'dev', stage: 'Development', status: 'HEALTHY' },
{ id: 'stage', stage: 'Staging', status: 'HEALTHY' },
{ id: 'prod', stage: 'Production', status: 'DEGRADED' },
];
}

View File

@@ -1,99 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
interface RegionCard {
id: string;
name: string;
envCount: number;
health: string;
sbomPosture: string;
}
@Component({
selector: 'app-regions-overview',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="regions-overview">
<header class="header">
<h1>Regions & Environments</h1>
<p>Region-first release control posture with environment health and SBOM coverage context.</p>
</header>
<div class="cards">
@for (region of regions; track region.id) {
<a class="card" [routerLink]="['/releases/environments', region.id]">
<h2>{{ region.name }}</h2>
<p>Environments: {{ region.envCount }}</p>
<p>Health: {{ region.health }}</p>
<p>SBOM posture: {{ region.sbomPosture }}</p>
</a>
}
</div>
</section>
`,
styles: [
`
.regions-overview {
display: grid;
gap: 0.9rem;
}
.header h1 {
margin: 0 0 0.2rem;
font-size: 1.45rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary);
font-size: 0.84rem;
}
.cards {
display: grid;
gap: 0.75rem;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.card {
border: 1px solid var(--color-border-primary);
border-radius: var(--radius-md);
background: var(--color-surface-primary);
padding: 0.75rem 0.85rem;
text-decoration: none;
color: inherit;
}
.card h2 {
margin: 0 0 0.35rem;
font-size: 1rem;
}
.card p {
margin: 0.15rem 0;
font-size: 0.82rem;
color: var(--color-text-secondary);
}
`,
],
})
export class RegionsOverviewComponent {
readonly regions: RegionCard[] = [
{
id: 'global',
name: 'Global',
envCount: 4,
health: 'DEGRADED',
sbomPosture: 'WARN',
},
{
id: 'eu-west',
name: 'EU West',
envCount: 3,
health: 'HEALTHY',
sbomPosture: 'OK',
},
];
}

View File

@@ -1,168 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
interface SetupArea {
title: string;
description: string;
route: string;
}
@Component({
selector: 'app-release-control-setup-home',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="setup-home">
<header class="header">
<h1>Release Control Setup</h1>
<p>
Canonical setup hub for environments, promotion paths, targets, agents, workflows, and
bundle templates.
</p>
</header>
<p class="state-banner">
Read-only structural mode: setup contracts are shown with deterministic placeholders until
backend setup APIs are wired.
</p>
<section class="areas" aria-label="Setup areas">
@for (area of areas; track area.route) {
<a class="card" [routerLink]="area.route">
<h2>{{ area.title }}</h2>
<p>{{ area.description }}</p>
</a>
}
</section>
<section class="legacy-map" aria-label="Legacy setup aliases">
<h2>Legacy Setup Aliases</h2>
<ul>
<li><code>/settings/release-control</code> redirects to <code>/release-control/setup</code></li>
<li>
<code>/settings/release-control/environments</code> redirects to
<code>/release-control/setup/environments-paths</code>
</li>
<li>
<code>/settings/release-control/targets</code> and <code>/settings/release-control/agents</code>
redirect to <code>/release-control/setup/targets-agents</code>
</li>
<li>
<code>/settings/release-control/workflows</code> redirects to
<code>/release-control/setup/workflows</code>
</li>
</ul>
</section>
</section>
`,
styles: [`
.setup-home {
padding: 1.5rem;
max-width: 1100px;
margin: 0 auto;
display: grid;
gap: 1rem;
}
.header h1 {
margin: 0 0 0.25rem;
font-size: 1.6rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary, #667085);
font-size: 0.92rem;
}
.state-banner {
margin: 0;
border: 1px solid var(--color-status-warning-border, #facc15);
background: var(--color-status-warning-bg, #fffbeb);
color: var(--color-status-warning-text, #854d0e);
border-radius: var(--radius-md, 8px);
padding: 0.7rem 0.85rem;
font-size: 0.86rem;
}
.areas {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 0.8rem;
}
.card {
display: block;
border: 1px solid var(--color-border-primary, #e4e7ec);
background: var(--color-surface-primary, #fff);
border-radius: var(--radius-md, 8px);
padding: 0.9rem;
text-decoration: none;
color: inherit;
transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.card:hover {
border-color: var(--color-brand-primary, #2563eb);
box-shadow: 0 3px 10px rgba(15, 23, 42, 0.08);
}
.card h2 {
margin: 0 0 0.25rem;
font-size: 1rem;
}
.card p {
margin: 0;
color: var(--color-text-secondary, #667085);
font-size: 0.84rem;
line-height: 1.4;
}
.legacy-map {
border: 1px solid var(--color-border-primary, #e4e7ec);
border-radius: var(--radius-md, 8px);
padding: 0.9rem;
background: var(--color-surface-primary, #fff);
}
.legacy-map h2 {
margin: 0 0 0.6rem;
font-size: 0.95rem;
}
.legacy-map ul {
margin: 0;
padding-left: 1.1rem;
display: grid;
gap: 0.45rem;
color: var(--color-text-secondary, #667085);
font-size: 0.83rem;
}
`],
})
export class ReleaseControlSetupHomeComponent {
readonly areas: SetupArea[] = [
{
title: 'Environments and Promotion Paths',
description: 'Define environment hierarchy and promotion routes (Dev -> Stage -> Prod).',
route: '/release-control/setup/environments-paths',
},
{
title: 'Targets and Agents',
description: 'Track runtime targets and execution agents used by release deployments.',
route: '/release-control/setup/targets-agents',
},
{
title: 'Workflows',
description: 'Review workflow templates and promotion execution steps before activation.',
route: '/release-control/setup/workflows',
},
{
title: 'Bundle Templates',
description: 'Manage default bundle composition templates and validation requirements.',
route: '/release-control/setup/bundle-templates',
},
];
}

View File

@@ -1,133 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-setup-bundle-templates',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="page">
<header class="header">
<a routerLink="/ops/platform-setup" class="back-link">Back to Setup</a>
<h1>Bundle Templates</h1>
<p>Template presets for bundle composition, validation gates, and release metadata policy.</p>
</header>
<section class="panel">
<h2>Template Catalog</h2>
<table aria-label="Bundle templates">
<thead>
<tr>
<th>Template</th>
<th>Required Sections</th>
<th>Validation Profile</th>
<th>Default Use</th>
</tr>
</thead>
<tbody>
<tr><td>service-platform</td><td>digest, config, changelog, evidence</td><td>strict</td><td>platform releases</td></tr>
<tr><td>edge-hotfix</td><td>digest, changelog, evidence</td><td>fast-track</td><td>hotfix bundle</td></tr>
<tr><td>regional-rollout</td><td>digest, config, promotion path, evidence</td><td>risk-aware</td><td>multi-region rollout</td></tr>
</tbody>
</table>
</section>
<section class="panel">
<h2>Template Rules</h2>
<ul>
<li>Template controls required builder sections before bundle version materialization.</li>
<li>Validation profile maps to policy and advisory confidence requirements.</li>
<li>Template changes apply only to newly created bundle versions (immutability preserved).</li>
</ul>
</section>
<section class="panel links">
<h2>Related Surfaces</h2>
<a routerLink="/releases/bundles/create">Open Bundle Builder</a>
<a routerLink="/releases/bundles">Open Bundle Catalog</a>
</section>
</section>
`,
styles: [`
.page {
padding: 1.5rem;
max-width: 980px;
margin: 0 auto;
display: grid;
gap: 1rem;
}
.back-link {
font-size: 0.84rem;
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
}
.header h1 {
margin: 0.25rem 0 0.2rem;
font-size: 1.4rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary, #667085);
}
.panel {
border: 1px solid var(--color-border-primary, #e4e7ec);
border-radius: var(--radius-md, 8px);
padding: 0.85rem;
background: var(--color-surface-primary, #fff);
}
.panel h2 {
margin: 0 0 0.6rem;
font-size: 0.96rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
th, td {
text-align: left;
padding: 0.45rem 0.35rem;
border-top: 1px solid var(--color-border-primary, #e4e7ec);
}
th {
border-top: 0;
font-size: 0.73rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
ul {
margin: 0;
padding-left: 1.1rem;
display: grid;
gap: 0.45rem;
color: var(--color-text-secondary, #667085);
font-size: 0.85rem;
}
.links {
display: grid;
gap: 0.5rem;
}
.links a {
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
font-size: 0.86rem;
}
`],
})
export class SetupBundleTemplatesComponent {}

View File

@@ -1,133 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-setup-environments-paths',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="page">
<header class="header">
<a routerLink="/ops/platform-setup" class="back-link">Back to Setup</a>
<h1>Environments and Promotion Paths</h1>
<p>Release Control-owned environment graph and allowed promotion flows.</p>
</header>
<section class="panel">
<h2>Environment Inventory</h2>
<table aria-label="Environment inventory">
<thead>
<tr>
<th>Environment</th>
<th>Region</th>
<th>Risk Tier</th>
<th>Promotion Entry</th>
</tr>
</thead>
<tbody>
<tr><td>dev-us-east</td><td>us-east</td><td>low</td><td>yes</td></tr>
<tr><td>stage-eu-west</td><td>eu-west</td><td>medium</td><td>yes</td></tr>
<tr><td>prod-eu-west</td><td>eu-west</td><td>high</td><td>yes</td></tr>
</tbody>
</table>
</section>
<section class="panel">
<h2>Promotion Path Rules</h2>
<ul>
<li><code>dev-*</code> can promote to <code>stage-*</code> with approval gates.</li>
<li><code>stage-*</code> can promote to <code>prod-*</code> only with policy + ops gate pass.</li>
<li>Cross-region promotion requires an explicit path definition and target parity checks.</li>
</ul>
</section>
<section class="panel links">
<h2>Related Surfaces</h2>
<a routerLink="/releases/environments">Open Regions and Environments</a>
<a routerLink="/releases/approvals">Open Promotions</a>
</section>
</section>
`,
styles: [`
.page {
padding: 1.5rem;
max-width: 980px;
margin: 0 auto;
display: grid;
gap: 1rem;
}
.back-link {
font-size: 0.84rem;
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
}
.header h1 {
margin: 0.25rem 0 0.2rem;
font-size: 1.4rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary, #667085);
}
.panel {
border: 1px solid var(--color-border-primary, #e4e7ec);
border-radius: var(--radius-md, 8px);
padding: 0.85rem;
background: var(--color-surface-primary, #fff);
}
.panel h2 {
margin: 0 0 0.6rem;
font-size: 0.96rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
th, td {
text-align: left;
padding: 0.45rem 0.35rem;
border-top: 1px solid var(--color-border-primary, #e4e7ec);
}
th {
border-top: 0;
font-size: 0.73rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
ul {
margin: 0;
padding-left: 1.1rem;
display: grid;
gap: 0.45rem;
color: var(--color-text-secondary, #667085);
font-size: 0.85rem;
}
.links {
display: grid;
gap: 0.5rem;
}
.links a {
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
font-size: 0.86rem;
}
`],
})
export class SetupEnvironmentsPathsComponent {}

View File

@@ -1,136 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-setup-targets-agents',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="page">
<header class="header">
<a routerLink="/ops/platform-setup" class="back-link">Back to Setup</a>
<h1>Targets and Agents</h1>
<p>Release Control deployment execution topology with ownership split to Integrations.</p>
</header>
<section class="panel">
<h2>Deployment Targets</h2>
<table aria-label="Deployment targets">
<thead>
<tr>
<th>Target</th>
<th>Runtime</th>
<th>Region</th>
<th>Agent Group</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr><td>edge-gateway-prod</td><td>vm</td><td>eu-west</td><td>agent-eu</td><td>ready</td></tr>
<tr><td>payments-core-stage</td><td>nomad</td><td>us-east</td><td>agent-us</td><td>ready</td></tr>
<tr><td>billing-svc-prod</td><td>ecs</td><td>eu-west</td><td>agent-eu</td><td>degraded</td></tr>
</tbody>
</table>
</section>
<section class="panel">
<h2>Agent Coverage</h2>
<ul>
<li><strong>agent-eu</strong>: 42 targets, heartbeat every 20s, upgrade window Fri 23:00 UTC.</li>
<li><strong>agent-us</strong>: 35 targets, heartbeat every 20s, upgrade window Sat 01:00 UTC.</li>
<li><strong>agent-apac</strong>: 18 targets, on-call watch enabled, runtime drift checks active.</li>
</ul>
</section>
<section class="panel links">
<h2>Ownership Links</h2>
<a routerLink="/integrations/hosts">
Connector connectivity and credentials are managed in Integrations > Targets / Runtimes
</a>
<a routerLink="/platform-ops/agents">Operational status and diagnostics are managed in Platform Ops > Agents</a>
</section>
</section>
`,
styles: [`
.page {
padding: 1.5rem;
max-width: 980px;
margin: 0 auto;
display: grid;
gap: 1rem;
}
.back-link {
font-size: 0.84rem;
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
}
.header h1 {
margin: 0.25rem 0 0.2rem;
font-size: 1.4rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary, #667085);
}
.panel {
border: 1px solid var(--color-border-primary, #e4e7ec);
border-radius: var(--radius-md, 8px);
padding: 0.85rem;
background: var(--color-surface-primary, #fff);
}
.panel h2 {
margin: 0 0 0.6rem;
font-size: 0.96rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
th, td {
text-align: left;
padding: 0.45rem 0.35rem;
border-top: 1px solid var(--color-border-primary, #e4e7ec);
}
th {
border-top: 0;
font-size: 0.73rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
ul {
margin: 0;
padding-left: 1.1rem;
display: grid;
gap: 0.45rem;
color: var(--color-text-secondary, #667085);
font-size: 0.85rem;
}
.links {
display: grid;
gap: 0.5rem;
}
.links a {
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
font-size: 0.86rem;
}
`],
})
export class SetupTargetsAgentsComponent {}

View File

@@ -1,133 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
@Component({
selector: 'app-setup-workflows',
standalone: true,
imports: [RouterLink],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<section class="page">
<header class="header">
<a routerLink="/ops/platform-setup" class="back-link">Back to Setup</a>
<h1>Workflows</h1>
<p>Release Control workflow definitions for promotion orchestration and approval sequencing.</p>
</header>
<section class="panel">
<h2>Workflow Catalog</h2>
<table aria-label="Workflow catalog">
<thead>
<tr>
<th>Workflow</th>
<th>Path</th>
<th>Gate Profile</th>
<th>Rollback</th>
</tr>
</thead>
<tbody>
<tr><td>standard-blue-green</td><td>dev -> stage -> prod</td><td>strict-prod</td><td>auto</td></tr>
<tr><td>canary-regional</td><td>stage -> prod-canary -> prod</td><td>risk-aware</td><td>manual</td></tr>
<tr><td>hotfix-fast-track</td><td>stage -> prod</td><td>expedited</td><td>manual</td></tr>
</tbody>
</table>
</section>
<section class="panel">
<h2>Execution Constraints</h2>
<ul>
<li>All workflows require a bundle version digest and resolved inputs before promotion launch.</li>
<li>Approval checkpoints inherit policy gates from Administration policy governance baseline.</li>
<li>Run timeline evidence checkpoints are mandatory for promotion completion.</li>
</ul>
</section>
<section class="panel links">
<h2>Related Surfaces</h2>
<a routerLink="/administration/workflows">Open legacy workflow editor surface</a>
<a routerLink="/releases/runs">Open Run Timeline</a>
</section>
</section>
`,
styles: [`
.page {
padding: 1.5rem;
max-width: 980px;
margin: 0 auto;
display: grid;
gap: 1rem;
}
.back-link {
font-size: 0.84rem;
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
}
.header h1 {
margin: 0.25rem 0 0.2rem;
font-size: 1.4rem;
}
.header p {
margin: 0;
color: var(--color-text-secondary, #667085);
}
.panel {
border: 1px solid var(--color-border-primary, #e4e7ec);
border-radius: var(--radius-md, 8px);
padding: 0.85rem;
background: var(--color-surface-primary, #fff);
}
.panel h2 {
margin: 0 0 0.6rem;
font-size: 0.96rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.84rem;
}
th, td {
text-align: left;
padding: 0.45rem 0.35rem;
border-top: 1px solid var(--color-border-primary, #e4e7ec);
}
th {
border-top: 0;
font-size: 0.73rem;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text-secondary, #667085);
}
ul {
margin: 0;
padding-left: 1.1rem;
display: grid;
gap: 0.45rem;
color: var(--color-text-secondary, #667085);
font-size: 0.85rem;
}
.links {
display: grid;
gap: 0.5rem;
}
.links a {
color: var(--color-brand-primary, #2563eb);
text-decoration: none;
font-size: 0.86rem;
}
`],
})
export class SetupWorkflowsComponent {}

View File

@@ -1,13 +0,0 @@
// Copyright (c) Stella Ops. All rights reserved. SPDX-License-Identifier: BUSL-1.1
import { Routes } from '@angular/router';
export const workflowVisualizationRoutes: Routes = [
{
path: '',
loadComponent: () =>
import('./components/workflow-visualizer/workflow-visualizer.component').then(
(m) => m.WorkflowVisualizerComponent
),
},
];

View File

@@ -1,72 +0,0 @@
import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { ReleaseControlSetupHomeComponent } from '../../app/features/release-control/setup/release-control-setup-home.component';
import { SetupBundleTemplatesComponent } from '../../app/features/release-control/setup/setup-bundle-templates.component';
import { SetupEnvironmentsPathsComponent } from '../../app/features/release-control/setup/setup-environments-paths.component';
import { SetupTargetsAgentsComponent } from '../../app/features/release-control/setup/setup-targets-agents.component';
import { SetupWorkflowsComponent } from '../../app/features/release-control/setup/setup-workflows.component';
describe('Release Control setup components (release-control)', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
ReleaseControlSetupHomeComponent,
SetupEnvironmentsPathsComponent,
SetupTargetsAgentsComponent,
SetupWorkflowsComponent,
SetupBundleTemplatesComponent,
],
providers: [provideRouter([])],
}).compileComponents();
});
it('setup home renders required setup areas', () => {
const fixture = TestBed.createComponent(ReleaseControlSetupHomeComponent);
fixture.detectChanges();
const text = fixture.nativeElement.textContent as string;
expect(text).toContain('Release Control Setup');
expect(text).toContain('Environments and Promotion Paths');
expect(text).toContain('Targets and Agents');
expect(text).toContain('Workflows');
expect(text).toContain('Bundle Templates');
});
it('environments and paths page renders inventory and path rules', () => {
const fixture = TestBed.createComponent(SetupEnvironmentsPathsComponent);
fixture.detectChanges();
const text = fixture.nativeElement.textContent as string;
expect(text).toContain('Environment Inventory');
expect(text).toContain('Promotion Path Rules');
});
it('targets and agents page renders ownership links', () => {
const fixture = TestBed.createComponent(SetupTargetsAgentsComponent);
fixture.detectChanges();
const text = fixture.nativeElement.textContent as string;
expect(text).toContain('Targets and Agents');
expect(text).toContain('Integrations > Targets / Runtimes');
expect(text).toContain('Platform Ops > Agents');
});
it('workflows page renders workflow catalog and run timeline link', () => {
const fixture = TestBed.createComponent(SetupWorkflowsComponent);
fixture.detectChanges();
const text = fixture.nativeElement.textContent as string;
expect(text).toContain('Workflow Catalog');
expect(text).toContain('Open Run Timeline');
});
it('bundle templates page renders template catalog and builder link', () => {
const fixture = TestBed.createComponent(SetupBundleTemplatesComponent);
fixture.detectChanges();
const text = fixture.nativeElement.textContent as string;
expect(text).toContain('Template Catalog');
expect(text).toContain('Open Bundle Builder');
});
});

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svgjs="http://svgjs.com/svgjs" xmlns:xlink="http://www.w3.org/1999/xlink" width="164" height="164" version="1.1"><svg xmlns="http://www.w3.org/2000/svg" width="164" height="164" fill="none" viewBox="0 0 164 164"><path fill="#FF4785" d="M22.467 147.762 17.5 15.402a8.062 8.062 0 0 1 7.553-8.35L137.637.016a8.061 8.061 0 0 1 8.565 8.047v144.23a8.063 8.063 0 0 1-8.424 8.054l-107.615-4.833a8.062 8.062 0 0 1-7.695-7.752Z"/><path fill="#fff" fill-rule="evenodd" d="m128.785.57-15.495.968-.755 18.172a1.203 1.203 0 0 0 1.928 1.008l7.06-5.354 5.962 4.697a1.202 1.202 0 0 0 1.946-.987L128.785.569Zm-12.059 60.856c-2.836 2.203-23.965 3.707-23.965.57.447-11.969-4.912-12.494-7.889-12.494-2.828 0-7.59.855-7.59 7.267 0 6.534 6.96 10.223 15.13 14.553 11.607 6.15 25.654 13.594 25.654 32.326 0 17.953-14.588 27.871-33.194 27.871-19.201 0-35.981-7.769-34.086-34.702.744-3.163 25.156-2.411 25.156 0-.298 11.114 2.232 14.383 8.633 14.383 4.912 0 7.144-2.708 7.144-7.267 0-6.9-7.252-10.973-15.595-15.657C64.827 81.933 51.53 74.468 51.53 57.34c0-17.098 11.76-28.497 32.747-28.497 20.988 0 32.449 11.224 32.449 32.584Z" clip-rule="evenodd"/></svg><style>@media (prefers-color-scheme:light){:root{filter:none}}</style></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,177 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>@storybook/angular - Storybook</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
<style>
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-regular.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-italic.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-bold.woff2') format('woff2');
}
@font-face {
font-family: 'Nunito Sans';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url('./sb-common-assets/nunito-sans-bold-italic.woff2') format('woff2');
}
</style>
<link href="./sb-manager/runtime.js" rel="modulepreload" />
<link href="./sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-controls-1/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-actions-2/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-docs-3/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-backgrounds-4/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-viewport-5/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-toolbars-6/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-measure-7/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/essentials-outline-8/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/a11y-9/manager-bundle.js" rel="modulepreload" />
<link href="./sb-addons/interactions-10/manager-bundle.js" rel="modulepreload" />
<style>
#storybook-root[hidden] {
display: none !important;
}
</style>
</head>
<body>
<div id="root"></div>
<script>
window['FEATURES'] = {
"argTypeTargetsV7": true,
"legacyDecoratorFileOrder": false,
"disallowImplicitActionsInRenderV8": true
};
window['REFS'] = {};
window['LOGLEVEL'] = "info";
window['DOCS_OPTIONS'] = {
"defaultName": "Docs",
"autodocs": "tag"
};
window['CONFIG_TYPE'] = "PRODUCTION";
window['TAGS_OPTIONS'] = {
"dev-only": {
"excludeFromDocsStories": true
},
"docs-only": {
"excludeFromSidebar": true
},
"test-only": {
"excludeFromSidebar": true,
"excludeFromDocsStories": true
}
};
window['STORYBOOK_RENDERER'] = "angular";
window['STORYBOOK_BUILDER'] = "@storybook/builder-webpack5";
window['STORYBOOK_FRAMEWORK'] = "@storybook/angular";
</script>
<script type="module">
import './sb-manager/globals-runtime.js';
import './sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js';
import './sb-addons/essentials-controls-1/manager-bundle.js';
import './sb-addons/essentials-actions-2/manager-bundle.js';
import './sb-addons/essentials-docs-3/manager-bundle.js';
import './sb-addons/essentials-backgrounds-4/manager-bundle.js';
import './sb-addons/essentials-viewport-5/manager-bundle.js';
import './sb-addons/essentials-toolbars-6/manager-bundle.js';
import './sb-addons/essentials-measure-7/manager-bundle.js';
import './sb-addons/essentials-outline-8/manager-bundle.js';
import './sb-addons/a11y-9/manager-bundle.js';
import './sb-addons/interactions-10/manager-bundle.js';
import './sb-manager/runtime.js';
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -1 +0,0 @@
{"generatedAt":1770045794032,"userSince":1770045051724,"hasCustomBabel":false,"hasCustomWebpack":false,"hasStaticDirs":false,"hasStorybookEslint":false,"refCount":0,"testPackages":{"@axe-core/playwright":"4.8.4","@playwright/test":"1.56.1","@types/jasmine":"5.1.12","jasmine-core":"5.1.2","karma":"6.4.4","karma-chrome-launcher":"3.2.0","karma-coverage":"2.2.1","karma-jasmine":"5.1.0","karma-jasmine-html-reporter":"2.1.0"},"hasRouterPackage":true,"packageManager":{"type":"npm","agent":"npm"},"preview":{"usesGlobals":true},"framework":{"name":"@storybook/angular","options":{}},"builder":"@storybook/builder-webpack5","renderer":"@storybook/angular","portableStoriesFileCount":0,"applicationFileCount":58,"storybookVersion":"8.6.14","storybookVersionSpecifier":"^8.6.14","language":"typescript","storybookPackages":{"@chromatic-com/storybook":{"version":"5.0.0"},"@storybook/angular":{"version":"8.6.14"},"@storybook/test":{"version":"8.6.14"},"storybook":{"version":"8.6.14"}},"addons":{"@storybook/addon-essentials":{"version":"8.6.14"},"@storybook/addon-a11y":{"version":"8.6.14"},"@storybook/addon-interactions":{"version":"8.6.14"}}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
try{
(()=>{var T=__STORYBOOK_API__,{ActiveTabs:h,Consumer:g,ManagerContext:f,Provider:v,RequestResponseError:A,addons:n,combineParameters:x,controlOrMetaKey:P,controlOrMetaSymbol:k,eventMatchesShortcut:M,eventToShortcut:R,experimental_MockUniversalStore:C,experimental_UniversalStore:U,experimental_requestResponse:w,experimental_useUniversalStore:B,isMacLike:E,isShortcutTaken:I,keyToSymbol:K,merge:N,mockChannel:G,optionOrAltSymbol:L,shortcutMatchesShortcut:Y,shortcutToHumanString:q,types:D,useAddonState:F,useArgTypes:H,useArgs:j,useChannel:V,useGlobalTypes:z,useGlobals:J,useParameter:Q,useSharedState:W,useStoryPrepared:X,useStorybookApi:Z,useStorybookState:$}=__STORYBOOK_API__;var S=(()=>{let e;return typeof window<"u"?e=window:typeof globalThis<"u"?e=globalThis:typeof window<"u"?e=window:typeof self<"u"?e=self:e={},e})(),c="tag-filters",p="static-filter";n.register(c,e=>{let u=Object.entries(S.TAGS_OPTIONS??{}).reduce((t,r)=>{let[o,i]=r;return i.excludeFromSidebar&&(t[o]=!0),t},{});e.experimental_setFilter(p,t=>{let r=t.tags??[];return(r.includes("dev")||t.type==="docs")&&r.filter(o=>u[o]).length===0})});})();
}catch(e){ console.error("[Storybook] One of your manager-entries failed: " + import.meta.url, e); }

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:svgjs="http://svgjs.com/svgjs" xmlns:xlink="http://www.w3.org/1999/xlink" width="164" height="164" version="1.1"><svg xmlns="http://www.w3.org/2000/svg" width="164" height="164" fill="none" viewBox="0 0 164 164"><path fill="#FF4785" d="M22.467 147.762 17.5 15.402a8.062 8.062 0 0 1 7.553-8.35L137.637.016a8.061 8.061 0 0 1 8.565 8.047v144.23a8.063 8.063 0 0 1-8.424 8.054l-107.615-4.833a8.062 8.062 0 0 1-7.695-7.752Z"/><path fill="#fff" fill-rule="evenodd" d="m128.785.57-15.495.968-.755 18.172a1.203 1.203 0 0 0 1.928 1.008l7.06-5.354 5.962 4.697a1.202 1.202 0 0 0 1.946-.987L128.785.569Zm-12.059 60.856c-2.836 2.203-23.965 3.707-23.965.57.447-11.969-4.912-12.494-7.889-12.494-2.828 0-7.59.855-7.59 7.267 0 6.534 6.96 10.223 15.13 14.553 11.607 6.15 25.654 13.594 25.654 32.326 0 17.953-14.588 27.871-33.194 27.871-19.201 0-35.981-7.769-34.086-34.702.744-3.163 25.156-2.411 25.156 0-.298 11.114 2.232 14.383 8.633 14.383 4.912 0 7.144-2.708 7.144-7.267 0-6.9-7.252-10.973-15.595-15.657C64.827 81.933 51.53 74.468 51.53 57.34c0-17.098 11.76-28.497 32.747-28.497 20.988 0 32.449 11.224 32.449 32.584Z" clip-rule="evenodd"/></svg><style>@media (prefers-color-scheme:light){:root{filter:none}}</style></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1,48 +0,0 @@
import ESM_COMPAT_Module from "node:module";
import { fileURLToPath as ESM_COMPAT_fileURLToPath } from 'node:url';
import { dirname as ESM_COMPAT_dirname } from 'node:path';
const __filename = ESM_COMPAT_fileURLToPath(import.meta.url);
const __dirname = ESM_COMPAT_dirname(__filename);
const require = ESM_COMPAT_Module.createRequire(import.meta.url);
// src/manager/globals/globals.ts
var _ = {
react: "__REACT__",
"react-dom": "__REACT_DOM__",
"react-dom/client": "__REACT_DOM_CLIENT__",
"@storybook/icons": "__STORYBOOK_ICONS__",
"storybook/internal/manager-api": "__STORYBOOK_API__",
"@storybook/manager-api": "__STORYBOOK_API__",
"@storybook/core/manager-api": "__STORYBOOK_API__",
"storybook/internal/components": "__STORYBOOK_COMPONENTS__",
"@storybook/components": "__STORYBOOK_COMPONENTS__",
"@storybook/core/components": "__STORYBOOK_COMPONENTS__",
"storybook/internal/channels": "__STORYBOOK_CHANNELS__",
"@storybook/channels": "__STORYBOOK_CHANNELS__",
"@storybook/core/channels": "__STORYBOOK_CHANNELS__",
"storybook/internal/core-errors": "__STORYBOOK_CORE_EVENTS__",
"@storybook/core-events": "__STORYBOOK_CORE_EVENTS__",
"@storybook/core/core-events": "__STORYBOOK_CORE_EVENTS__",
"storybook/internal/manager-errors": "__STORYBOOK_CORE_EVENTS_MANAGER_ERRORS__",
"@storybook/core-events/manager-errors": "__STORYBOOK_CORE_EVENTS_MANAGER_ERRORS__",
"@storybook/core/manager-errors": "__STORYBOOK_CORE_EVENTS_MANAGER_ERRORS__",
"storybook/internal/router": "__STORYBOOK_ROUTER__",
"@storybook/router": "__STORYBOOK_ROUTER__",
"@storybook/core/router": "__STORYBOOK_ROUTER__",
"storybook/internal/theming": "__STORYBOOK_THEMING__",
"@storybook/theming": "__STORYBOOK_THEMING__",
"@storybook/core/theming": "__STORYBOOK_THEMING__",
"storybook/internal/theming/create": "__STORYBOOK_THEMING_CREATE__",
"@storybook/theming/create": "__STORYBOOK_THEMING_CREATE__",
"@storybook/core/theming/create": "__STORYBOOK_THEMING_CREATE__",
"storybook/internal/client-logger": "__STORYBOOK_CLIENT_LOGGER__",
"@storybook/client-logger": "__STORYBOOK_CLIENT_LOGGER__",
"@storybook/core/client-logger": "__STORYBOOK_CLIENT_LOGGER__",
"storybook/internal/types": "__STORYBOOK_TYPES__",
"@storybook/types": "__STORYBOOK_TYPES__",
"@storybook/core/types": "__STORYBOOK_TYPES__"
}, o = Object.keys(_);
export {
o as globalPackages,
_ as globalsNameReferenceMap
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,33 +0,0 @@
import ESM_COMPAT_Module from "node:module";
import { fileURLToPath as ESM_COMPAT_fileURLToPath } from 'node:url';
import { dirname as ESM_COMPAT_dirname } from 'node:path';
const __filename = ESM_COMPAT_fileURLToPath(import.meta.url);
const __dirname = ESM_COMPAT_dirname(__filename);
const require = ESM_COMPAT_Module.createRequire(import.meta.url);
// src/preview/globals/globals.ts
var _ = {
"@storybook/global": "__STORYBOOK_MODULE_GLOBAL__",
"storybook/internal/channels": "__STORYBOOK_MODULE_CHANNELS__",
"@storybook/channels": "__STORYBOOK_MODULE_CHANNELS__",
"@storybook/core/channels": "__STORYBOOK_MODULE_CHANNELS__",
"storybook/internal/client-logger": "__STORYBOOK_MODULE_CLIENT_LOGGER__",
"@storybook/client-logger": "__STORYBOOK_MODULE_CLIENT_LOGGER__",
"@storybook/core/client-logger": "__STORYBOOK_MODULE_CLIENT_LOGGER__",
"storybook/internal/core-events": "__STORYBOOK_MODULE_CORE_EVENTS__",
"@storybook/core-events": "__STORYBOOK_MODULE_CORE_EVENTS__",
"@storybook/core/core-events": "__STORYBOOK_MODULE_CORE_EVENTS__",
"storybook/internal/preview-errors": "__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__",
"@storybook/core-events/preview-errors": "__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__",
"@storybook/core/preview-errors": "__STORYBOOK_MODULE_CORE_EVENTS_PREVIEW_ERRORS__",
"storybook/internal/preview-api": "__STORYBOOK_MODULE_PREVIEW_API__",
"@storybook/preview-api": "__STORYBOOK_MODULE_PREVIEW_API__",
"@storybook/core/preview-api": "__STORYBOOK_MODULE_PREVIEW_API__",
"storybook/internal/types": "__STORYBOOK_MODULE_TYPES__",
"@storybook/types": "__STORYBOOK_MODULE_TYPES__",
"@storybook/core/types": "__STORYBOOK_MODULE_TYPES__"
}, O = Object.keys(_);
export {
O as globalPackages,
_ as globalsNameReferenceMap
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,58 +0,0 @@
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true, args: ['--disable-dev-shm-usage'] });
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
const events = [];
const push = (kind, payload) => events.push({ ts: new Date().toISOString(), kind, ...payload, page: page.url() });
page.on('console', msg => {
if (msg.type() === 'error') {
push('console_error', { text: msg.text() });
}
});
page.on('requestfailed', request => {
const url = request.url();
if (/\.(css|js|map|png|jpg|jpeg|svg|woff2?)($|\?)/i.test(url)) return;
push('request_failed', {
method: request.method(),
url,
error: request.failure()?.errorText ?? 'unknown'
});
});
page.on('response', response => {
const url = response.url();
if (/\.(css|js|map|png|jpg|jpeg|svg|woff2?)($|\?)/i.test(url)) return;
if (response.status() >= 400) {
push('response_error', { status: response.status(), method: response.request().method(), url });
}
});
await page.goto('https://stella-ops.local/welcome', { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(1200);
const cta = page.locator('button.cta').first();
if (await cta.count()) {
await cta.click({ force: true, noWaitAfter: true });
await page.waitForTimeout(1000);
}
if (page.url().includes('/connect/authorize')) {
await page.locator('input[name="username"]').first().fill('admin');
await page.locator('input[name="password"]').first().fill('Admin@Stella2026!');
await page.locator('button[type="submit"], button:has-text("Sign In")').first().click();
await page.waitForURL(url => !url.toString().includes('/connect/authorize'), { timeout: 20000 });
await page.waitForTimeout(1200);
}
for (const path of ['/evidence/proof-chains', '/policy/packs']) {
await page.goto(`https://stella-ops.local${path}`, { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(6000);
}
console.log(JSON.stringify(events, null, 2));
await browser.close();
})();

View File

@@ -1,49 +0,0 @@
const { chromium } = require('playwright');
const BASE='https://stella-ops.local';
const USER='admin';
const PASS='Admin@Stella2026!';
(async () => {
const browser = await chromium.launch({ headless: true, args:['--disable-dev-shm-usage'] });
const ctx = await browser.newContext({ ignoreHTTPSErrors: true, viewport:{width:1511,height:864} });
const page = await ctx.newPage();
const failed=[];
const responses=[];
page.on('requestfailed', req => {
const url=req.url();
if (/\.(css|js|map|png|jpg|jpeg|svg|woff2?)($|\?)/i.test(url)) return;
failed.push({ url, method:req.method(), error:req.failure()?.errorText || 'unknown', page: page.url() });
});
page.on('response', res => {
const url=res.url();
if (/\.(css|js|map|png|jpg|jpeg|svg|woff2?)($|\?)/i.test(url)) return;
if (res.status() >= 400) {
responses.push({ status: res.status(), method: res.request().method(), url, page: page.url() });
}
});
await page.goto(`${BASE}/welcome`, { waitUntil:'domcontentloaded' });
await page.waitForTimeout(1200);
const cta = page.locator('button.cta').first();
if (await cta.count()) {
await cta.click({ force:true, noWaitAfter:true });
await page.waitForTimeout(1200);
}
if (page.url().includes('/connect/authorize')) {
await page.locator('input[name="username"]').first().fill(USER);
await page.locator('input[name="password"]').first().fill(PASS);
await page.locator('button[type="submit"], button:has-text("Sign In")').first().click();
await page.waitForURL(url => !url.toString().includes('/connect/authorize'), { timeout: 20000 });
await page.waitForTimeout(1200);
}
for (const p of ['/security/exceptions','/evidence/proof-chains']) {
await page.goto(`${BASE}${p}`, { waitUntil:'domcontentloaded' });
await page.waitForTimeout(2200);
}
await browser.close();
console.log(JSON.stringify({ failed, responses }, null, 2));
})();

View File

@@ -1,65 +0,0 @@
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({ headless: true, args: ['--disable-dev-shm-usage'] });
const context = await browser.newContext({ ignoreHTTPSErrors: true });
const page = await context.newPage();
const failed = [];
const websockets = [];
page.on('requestfailed', request => {
const url = request.url();
if (/\.(css|js|map|png|jpg|jpeg|svg|woff2?)($|\?)/i.test(url)) {
return;
}
failed.push({
url,
method: request.method(),
error: request.failure()?.errorText ?? 'unknown',
page: page.url(),
});
});
page.on('websocket', socket => {
const record = { url: socket.url(), events: [] };
websockets.push(record);
socket.on('framesent', () => record.events.push('sent'));
socket.on('framereceived', () => record.events.push('recv'));
socket.on('close', () => record.events.push('close'));
});
page.on('console', msg => {
if (msg.type() === 'error') {
console.log('console-error', msg.text(), '@', page.url());
}
});
await page.goto('https://stella-ops.local/welcome', { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(1200);
const cta = page.locator('button.cta').first();
if (await cta.count()) {
await cta.click({ force: true, noWaitAfter: true });
await page.waitForTimeout(1200);
}
if (page.url().includes('/connect/authorize')) {
await page.locator('input[name="username"]').first().fill('admin');
await page.locator('input[name="password"]').first().fill('Admin@Stella2026!');
await page.locator('button[type="submit"], button:has-text("Sign In")').first().click();
await page.waitForURL(url => !url.toString().includes('/connect/authorize'), { timeout: 20000 });
await page.waitForTimeout(1200);
}
for (const path of ['/security/exceptions', '/evidence/proof-chains']) {
await page.goto(`https://stella-ops.local${path}`, { waitUntil: 'domcontentloaded' });
await page.waitForTimeout(3000);
}
const filteredFailed = failed.filter(item => !item.url.includes('/connect/authorize?'));
console.log(JSON.stringify({ filteredFailed, websockets }, null, 2));
await browser.close();
})();