d67347be77
## Thinking Path > - Paperclip orchestrates AI agents that need scoped, auditable access to secrets > - Hosted and external deployments need provider vault configuration without exposing secret values in Paperclip metadata > - AWS Secrets Manager vault setup previously required too much manual operator knowledge > - Provider vault discovery and removal belong together as an independent secrets-management improvement > - This pull request adds AWS provider vault discovery/prefill plus vault removal flows > - The benefit is a safer operator path for configuring external secret storage before higher-level cloud workflows depend on it ## What Changed - Added shared validators/types for AWS provider vault discovery payloads and safe provider metadata. - Implemented AWS provider vault discovery preview on the server. - Added provider vault removal service/route behavior. - Added Secrets page UI for discovery prefill, removal messaging, and related rendering coverage. - Added Storybook provider-vault fixtures and captured screenshots for the new UX states. ## Verification - `pnpm install --frozen-lockfile --ignore-scripts` - `pnpm exec vitest run packages/shared/src/validators/secret.test.ts server/src/__tests__/aws-secrets-manager-provider.test.ts server/src/__tests__/secrets-routes.test.ts server/src/__tests__/secrets-service.test.ts ui/src/pages/Secrets.render.test.tsx` - Result: 4 files passed, 1 embedded Postgres-backed file skipped on this host because local Postgres init was unavailable. - `pnpm --filter @paperclipai/ui exec vitest run src/pages/Secrets.render.test.tsx` - `pnpm --filter @paperclipai/ui typecheck` - Storybook screenshot capture against `Product/Secrets` on `http://127.0.0.1:60381/iframe.html?id=product-secrets--secrets-inventory&viewMode=story&globals=theme:dark` ## Screenshots Provider vaults tab after this change:  AWS discovery candidate flow:  Provider vault removal confirmation:  ## Risks - Secret provider metadata handling must remain non-sensitive; validators reject credential-bearing Vault URLs and sensitive AWS discovery keys. - AWS discovery depends on deployment credentials being configured correctly outside Paperclip-managed company secrets. > For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and discuss it in `#dev` before opening the PR. Feature PRs that overlap with planned core work may need to be redirected — check the roadmap first. See `CONTRIBUTING.md`. ## Model Used - OpenAI Codex, GPT-5-based coding agent with local shell/git/tool use. Exact hosted model ID and context-window size are not exposed by the local Paperclip adapter runtime. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] If this change affects the UI, I have included before/after screenshots - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
1639 lines
49 KiB
TypeScript
1639 lines
49 KiB
TypeScript
import type {
|
|
ActivityEvent,
|
|
Agent,
|
|
Approval,
|
|
AuthSession,
|
|
BudgetPolicySummary,
|
|
Company,
|
|
CompanySecret,
|
|
CompanySecretBinding,
|
|
CompanySecretProviderConfig,
|
|
DashboardSummary,
|
|
ExecutionWorkspace,
|
|
Goal,
|
|
Issue,
|
|
IssueDocument,
|
|
IssueLabel,
|
|
Project,
|
|
SecretAccessEvent,
|
|
SecretProviderConfigDiscoveryPreviewResult,
|
|
SecretProviderDescriptor,
|
|
SidebarBadges,
|
|
WorkspaceRuntimeService,
|
|
} from "@paperclipai/shared";
|
|
import type { RunForIssue } from "@/api/activity";
|
|
import type { LiveRunForIssue } from "@/api/heartbeats";
|
|
|
|
const now = new Date("2026-04-20T12:00:00.000Z");
|
|
const recent = (minutesAgo: number) => new Date(now.getTime() - minutesAgo * 60_000);
|
|
const storybookRepoRoot = "~/paperclip";
|
|
const storybookWorkspaceRoot = `${storybookRepoRoot}/.paperclip/workspaces`;
|
|
const storybookWorktreeRoot = `${storybookRepoRoot}/.paperclip/worktrees`;
|
|
|
|
export const storybookCompanies: Company[] = [
|
|
{
|
|
id: "company-storybook",
|
|
name: "Paperclip Storybook",
|
|
description: "Fixture company for isolated UI review.",
|
|
status: "active",
|
|
pauseReason: null,
|
|
pausedAt: null,
|
|
issuePrefix: "PAP",
|
|
issueCounter: 1641,
|
|
budgetMonthlyCents: 250_000,
|
|
spentMonthlyCents: 67_500,
|
|
attachmentMaxBytes: 10 * 1024 * 1024,
|
|
requireBoardApprovalForNewAgents: true,
|
|
feedbackDataSharingEnabled: true,
|
|
feedbackDataSharingConsentAt: null,
|
|
feedbackDataSharingConsentByUserId: null,
|
|
feedbackDataSharingTermsVersion: null,
|
|
brandColor: "#0f766e",
|
|
logoAssetId: null,
|
|
logoUrl: null,
|
|
createdAt: new Date("2026-04-01T09:00:00.000Z"),
|
|
updatedAt: now,
|
|
},
|
|
{
|
|
id: "company-research",
|
|
name: "Research Bureau",
|
|
description: "A second active company for rail and switcher state coverage.",
|
|
status: "active",
|
|
pauseReason: null,
|
|
pausedAt: null,
|
|
issuePrefix: "RES",
|
|
issueCounter: 88,
|
|
budgetMonthlyCents: 180_000,
|
|
spentMonthlyCents: 39_500,
|
|
attachmentMaxBytes: 10 * 1024 * 1024,
|
|
requireBoardApprovalForNewAgents: false,
|
|
feedbackDataSharingEnabled: false,
|
|
feedbackDataSharingConsentAt: null,
|
|
feedbackDataSharingConsentByUserId: null,
|
|
feedbackDataSharingTermsVersion: null,
|
|
brandColor: "#4f46e5",
|
|
logoAssetId: null,
|
|
logoUrl: null,
|
|
createdAt: new Date("2026-04-03T09:00:00.000Z"),
|
|
updatedAt: recent(10),
|
|
},
|
|
{
|
|
id: "company-paused",
|
|
name: "Launch Ops",
|
|
description: "Paused company for inactive switcher treatment.",
|
|
status: "paused",
|
|
pauseReason: "manual",
|
|
pausedAt: recent(240),
|
|
issuePrefix: "OPS",
|
|
issueCounter: 204,
|
|
budgetMonthlyCents: 90_000,
|
|
spentMonthlyCents: 91_200,
|
|
attachmentMaxBytes: 10 * 1024 * 1024,
|
|
requireBoardApprovalForNewAgents: true,
|
|
feedbackDataSharingEnabled: false,
|
|
feedbackDataSharingConsentAt: null,
|
|
feedbackDataSharingConsentByUserId: null,
|
|
feedbackDataSharingTermsVersion: null,
|
|
brandColor: "#c2410c",
|
|
logoAssetId: null,
|
|
logoUrl: null,
|
|
createdAt: new Date("2026-04-05T09:00:00.000Z"),
|
|
updatedAt: recent(240),
|
|
},
|
|
];
|
|
|
|
export const storybookAuthSession: AuthSession = {
|
|
session: {
|
|
id: "session-storybook",
|
|
userId: "user-board",
|
|
},
|
|
user: {
|
|
id: "user-board",
|
|
name: "Riley Board",
|
|
email: "riley@paperclip.local",
|
|
image: null,
|
|
},
|
|
};
|
|
|
|
export const storybookAgents: Agent[] = [
|
|
{
|
|
id: "agent-codex",
|
|
companyId: "company-storybook",
|
|
name: "CodexCoder",
|
|
urlKey: "codexcoder",
|
|
role: "engineer",
|
|
title: "Senior Product Engineer",
|
|
icon: "code",
|
|
status: "running",
|
|
reportsTo: "agent-cto",
|
|
capabilities: "Ships full-stack Paperclip product tasks, Storybook coverage, and verification.",
|
|
adapterType: "codex_local",
|
|
adapterConfig: {},
|
|
runtimeConfig: {},
|
|
budgetMonthlyCents: 125_000,
|
|
spentMonthlyCents: 43_200,
|
|
pauseReason: null,
|
|
pausedAt: null,
|
|
permissions: { canCreateAgents: false },
|
|
lastHeartbeatAt: recent(3),
|
|
metadata: null,
|
|
createdAt: recent(12_000),
|
|
updatedAt: recent(3),
|
|
},
|
|
{
|
|
id: "agent-qa",
|
|
companyId: "company-storybook",
|
|
name: "QAChecker",
|
|
urlKey: "qachecker",
|
|
role: "qa",
|
|
title: "QA Engineer",
|
|
icon: "shield",
|
|
status: "idle",
|
|
reportsTo: "agent-cto",
|
|
capabilities: "Validates browser flows, acceptance criteria, and release smoke tests.",
|
|
adapterType: "claude_local",
|
|
adapterConfig: {},
|
|
runtimeConfig: {},
|
|
budgetMonthlyCents: 80_000,
|
|
spentMonthlyCents: 18_900,
|
|
pauseReason: null,
|
|
pausedAt: null,
|
|
permissions: { canCreateAgents: false },
|
|
lastHeartbeatAt: recent(24),
|
|
metadata: null,
|
|
createdAt: recent(11_000),
|
|
updatedAt: recent(24),
|
|
},
|
|
{
|
|
id: "agent-cto",
|
|
companyId: "company-storybook",
|
|
name: "CTO",
|
|
urlKey: "cto",
|
|
role: "cto",
|
|
title: "CTO",
|
|
icon: "crown",
|
|
status: "active",
|
|
reportsTo: null,
|
|
capabilities: "Reviews architecture, quality gates, and engineering priority tradeoffs.",
|
|
adapterType: "codex_local",
|
|
adapterConfig: {},
|
|
runtimeConfig: {},
|
|
budgetMonthlyCents: 200_000,
|
|
spentMonthlyCents: 54_000,
|
|
pauseReason: null,
|
|
pausedAt: null,
|
|
permissions: { canCreateAgents: true },
|
|
lastHeartbeatAt: recent(41),
|
|
metadata: null,
|
|
createdAt: recent(14_000),
|
|
updatedAt: recent(41),
|
|
},
|
|
];
|
|
|
|
export const storybookAgentMap = new Map(storybookAgents.map((agent) => [agent.id, agent]));
|
|
|
|
export const storybookIssueLabels: IssueLabel[] = [
|
|
{
|
|
id: "label-ui",
|
|
companyId: "company-storybook",
|
|
name: "UI",
|
|
color: "#0f766e",
|
|
createdAt: recent(20_000),
|
|
updatedAt: recent(20_000),
|
|
},
|
|
{
|
|
id: "label-docs",
|
|
companyId: "company-storybook",
|
|
name: "Design system",
|
|
color: "#f59e0b",
|
|
createdAt: recent(20_000),
|
|
updatedAt: recent(20_000),
|
|
},
|
|
{
|
|
id: "label-backend",
|
|
companyId: "company-storybook",
|
|
name: "API",
|
|
color: "#2563eb",
|
|
createdAt: recent(18_000),
|
|
updatedAt: recent(18_000),
|
|
},
|
|
{
|
|
id: "label-risk",
|
|
companyId: "company-storybook",
|
|
name: "Risk",
|
|
color: "#dc2626",
|
|
createdAt: recent(16_000),
|
|
updatedAt: recent(16_000),
|
|
},
|
|
];
|
|
|
|
const storybookIssueLabelMap = new Map(storybookIssueLabels.map((label) => [label.id, label]));
|
|
|
|
function labelsFor(ids: string[]) {
|
|
return ids.map((id) => storybookIssueLabelMap.get(id)).filter((label): label is IssueLabel => Boolean(label));
|
|
}
|
|
|
|
export const storybookGoals: Goal[] = [
|
|
{
|
|
id: "goal-company",
|
|
companyId: "company-storybook",
|
|
title: "Build Paperclip",
|
|
description: "Make Paperclip the control plane operators trust for autonomous AI companies.",
|
|
level: "company",
|
|
status: "active",
|
|
parentId: null,
|
|
ownerAgentId: "agent-cto",
|
|
createdAt: recent(30_000),
|
|
updatedAt: recent(8),
|
|
},
|
|
{
|
|
id: "goal-board-ux",
|
|
companyId: "company-storybook",
|
|
title: "Tighten board operator visibility",
|
|
description: "Every project, goal, and workspace surface should reveal ownership, progress, and runtime state at a glance.",
|
|
level: "team",
|
|
status: "active",
|
|
parentId: "goal-company",
|
|
ownerAgentId: "agent-codex",
|
|
createdAt: recent(19_000),
|
|
updatedAt: recent(18),
|
|
},
|
|
{
|
|
id: "goal-agent-runtime",
|
|
companyId: "company-storybook",
|
|
title: "Stabilize agent runtime loops",
|
|
description: "Keep local and isolated workspaces predictable while preserving operator control.",
|
|
level: "team",
|
|
status: "planned",
|
|
parentId: "goal-company",
|
|
ownerAgentId: "agent-cto",
|
|
createdAt: recent(17_500),
|
|
updatedAt: recent(60),
|
|
},
|
|
{
|
|
id: "goal-storybook",
|
|
companyId: "company-storybook",
|
|
title: "Complete Storybook review coverage",
|
|
description: "Capture dense board UI states in fixture-backed stories before release review.",
|
|
level: "task",
|
|
status: "active",
|
|
parentId: "goal-board-ux",
|
|
ownerAgentId: "agent-codex",
|
|
createdAt: recent(9_000),
|
|
updatedAt: recent(3),
|
|
},
|
|
{
|
|
id: "goal-budget-safety",
|
|
companyId: "company-storybook",
|
|
title: "Enforce spend guardrails",
|
|
description: "Budget hard stops should be visible before they surprise operators.",
|
|
level: "agent",
|
|
status: "achieved",
|
|
parentId: "goal-agent-runtime",
|
|
ownerAgentId: "agent-qa",
|
|
createdAt: recent(12_000),
|
|
updatedAt: recent(120),
|
|
},
|
|
{
|
|
id: "goal-archived-import",
|
|
companyId: "company-storybook",
|
|
title: "Retire old import wizard",
|
|
description: "Legacy import wizard work is preserved for audit only.",
|
|
level: "task",
|
|
status: "cancelled",
|
|
parentId: "goal-board-ux",
|
|
ownerAgentId: null,
|
|
createdAt: recent(24_000),
|
|
updatedAt: recent(2_500),
|
|
},
|
|
];
|
|
|
|
function createRuntimeService(
|
|
overrides: Partial<WorkspaceRuntimeService> = {},
|
|
): WorkspaceRuntimeService {
|
|
return {
|
|
id: overrides.id ?? "service-storybook",
|
|
companyId: overrides.companyId ?? "company-storybook",
|
|
projectId: overrides.projectId ?? "project-board-ui",
|
|
projectWorkspaceId: overrides.projectWorkspaceId ?? "workspace-board-ui",
|
|
executionWorkspaceId: overrides.executionWorkspaceId ?? "execution-workspace-storybook",
|
|
issueId: overrides.issueId ?? "issue-storybook-1",
|
|
scopeType: overrides.scopeType ?? "execution_workspace",
|
|
scopeId: overrides.scopeId ?? "execution-workspace-storybook",
|
|
serviceName: overrides.serviceName ?? "storybook",
|
|
status: overrides.status ?? "running",
|
|
lifecycle: overrides.lifecycle ?? "ephemeral",
|
|
reuseKey: overrides.reuseKey ?? "storybook",
|
|
command: overrides.command ?? "pnpm storybook",
|
|
cwd: overrides.cwd ?? `${storybookRepoRoot}/ui`,
|
|
port: overrides.port ?? 6006,
|
|
url: overrides.url ?? "http://localhost:6006",
|
|
provider: overrides.provider ?? "local_process",
|
|
providerRef: overrides.providerRef ?? null,
|
|
ownerAgentId: overrides.ownerAgentId ?? "agent-codex",
|
|
startedByRunId: overrides.startedByRunId ?? "run-storybook",
|
|
lastUsedAt: overrides.lastUsedAt ?? recent(4),
|
|
startedAt: overrides.startedAt ?? recent(16),
|
|
stoppedAt: overrides.stoppedAt ?? null,
|
|
stopPolicy: overrides.stopPolicy ?? null,
|
|
healthStatus: overrides.healthStatus ?? "healthy",
|
|
configIndex: overrides.configIndex ?? 0,
|
|
createdAt: overrides.createdAt ?? recent(16),
|
|
updatedAt: overrides.updatedAt ?? recent(4),
|
|
};
|
|
}
|
|
|
|
const storybookWorkspaceRuntime = {
|
|
commands: [
|
|
{
|
|
id: "storybook",
|
|
name: "Storybook",
|
|
kind: "service",
|
|
command: "pnpm storybook",
|
|
cwd: "ui",
|
|
lifecycle: "shared",
|
|
},
|
|
{
|
|
id: "typecheck-ui",
|
|
name: "UI typecheck",
|
|
kind: "job",
|
|
command: "pnpm --filter @paperclipai/ui typecheck",
|
|
cwd: ".",
|
|
},
|
|
],
|
|
};
|
|
|
|
export const storybookProjectWorkspaces: Project["workspaces"] = [
|
|
{
|
|
id: "workspace-board-ui",
|
|
companyId: "company-storybook",
|
|
projectId: "project-board-ui",
|
|
name: "Board UI",
|
|
sourceType: "local_path" as const,
|
|
cwd: `${storybookRepoRoot}/ui`,
|
|
repoUrl: "https://github.com/paperclipai/paperclip",
|
|
repoRef: "master",
|
|
defaultRef: "master",
|
|
visibility: "default" as const,
|
|
setupCommand: "pnpm install",
|
|
cleanupCommand: null,
|
|
remoteProvider: null,
|
|
remoteWorkspaceRef: null,
|
|
sharedWorkspaceKey: "board-ui",
|
|
metadata: null,
|
|
runtimeConfig: {
|
|
workspaceRuntime: storybookWorkspaceRuntime,
|
|
desiredState: "running" as const,
|
|
serviceStates: { storybook: "running" as const },
|
|
},
|
|
isPrimary: true,
|
|
runtimeServices: [createRuntimeService()],
|
|
createdAt: recent(20_000),
|
|
updatedAt: recent(4),
|
|
},
|
|
{
|
|
id: "workspace-docs-remote",
|
|
companyId: "company-storybook",
|
|
projectId: "project-board-ui",
|
|
name: "Docs preview sandbox",
|
|
sourceType: "remote_managed",
|
|
cwd: null,
|
|
repoUrl: "https://github.com/paperclipai/paperclip",
|
|
repoRef: "preview/docs-workspaces",
|
|
defaultRef: "master",
|
|
visibility: "advanced",
|
|
setupCommand: "pnpm install",
|
|
cleanupCommand: "pnpm dev:stop",
|
|
remoteProvider: "vercel_sandbox",
|
|
remoteWorkspaceRef: "vcsb_storybook_docs_0420",
|
|
sharedWorkspaceKey: "docs-preview",
|
|
metadata: { region: "iad1", ttlHours: 8 },
|
|
runtimeConfig: {
|
|
workspaceRuntime: {
|
|
commands: [
|
|
{
|
|
id: "docs",
|
|
name: "Docs preview",
|
|
kind: "service",
|
|
command: "pnpm docs:dev",
|
|
cwd: ".",
|
|
lifecycle: "ephemeral",
|
|
},
|
|
],
|
|
},
|
|
desiredState: "stopped",
|
|
serviceStates: { docs: "stopped" },
|
|
},
|
|
isPrimary: false,
|
|
runtimeServices: [
|
|
createRuntimeService({
|
|
id: "service-docs-preview",
|
|
projectWorkspaceId: "workspace-docs-remote",
|
|
executionWorkspaceId: null,
|
|
issueId: "issue-storybook-6",
|
|
scopeType: "project_workspace",
|
|
scopeId: "workspace-docs-remote",
|
|
serviceName: "docs",
|
|
status: "stopped",
|
|
lifecycle: "ephemeral",
|
|
reuseKey: "docs-preview",
|
|
command: "pnpm docs:dev",
|
|
cwd: null,
|
|
port: 4173,
|
|
url: "https://paperclip-docs-preview.vercel.app",
|
|
healthStatus: "unknown",
|
|
lastUsedAt: recent(48),
|
|
startedAt: recent(72),
|
|
stoppedAt: recent(46),
|
|
createdAt: recent(72),
|
|
updatedAt: recent(46),
|
|
}),
|
|
],
|
|
createdAt: recent(2_000),
|
|
updatedAt: recent(46),
|
|
},
|
|
{
|
|
id: "workspace-release-local",
|
|
companyId: "company-storybook",
|
|
projectId: "project-board-ui",
|
|
name: "Release smoke local checkout",
|
|
sourceType: "local_path",
|
|
cwd: `${storybookWorkspaceRoot}/release-smoke`,
|
|
repoUrl: "https://github.com/paperclipai/paperclip",
|
|
repoRef: "release/smoke-2026-04-20",
|
|
defaultRef: "master",
|
|
visibility: "advanced",
|
|
setupCommand: "pnpm install",
|
|
cleanupCommand: "pnpm dev:stop",
|
|
remoteProvider: null,
|
|
remoteWorkspaceRef: null,
|
|
sharedWorkspaceKey: "release-smoke",
|
|
metadata: null,
|
|
runtimeConfig: {
|
|
workspaceRuntime: {
|
|
commands: [
|
|
{
|
|
id: "release-smoke",
|
|
name: "Release smoke",
|
|
kind: "job",
|
|
command: "pnpm test:release-smoke",
|
|
cwd: ".",
|
|
},
|
|
],
|
|
},
|
|
desiredState: "stopped",
|
|
serviceStates: null,
|
|
},
|
|
isPrimary: false,
|
|
runtimeServices: [],
|
|
createdAt: recent(7_200),
|
|
updatedAt: recent(90),
|
|
},
|
|
];
|
|
|
|
export const storybookExecutionWorkspaces: ExecutionWorkspace[] = [
|
|
{
|
|
id: "execution-workspace-storybook",
|
|
companyId: "company-storybook",
|
|
projectId: "project-board-ui",
|
|
projectWorkspaceId: "workspace-board-ui",
|
|
sourceIssueId: "issue-storybook-1",
|
|
mode: "isolated_workspace",
|
|
strategyType: "git_worktree",
|
|
name: "PAP-1641 storybook worktree",
|
|
status: "active",
|
|
cwd: `${storybookWorktreeRoot}/PAP-1641-create-super-detailed-storybooks-for-our-project`,
|
|
repoUrl: "https://github.com/paperclipai/paperclip",
|
|
baseRef: "master",
|
|
branchName: "PAP-1641-create-super-detailed-storybooks-for-our-project",
|
|
providerType: "git_worktree",
|
|
providerRef: null,
|
|
derivedFromExecutionWorkspaceId: null,
|
|
lastUsedAt: recent(3),
|
|
openedAt: recent(90),
|
|
closedAt: null,
|
|
cleanupEligibleAt: null,
|
|
cleanupReason: null,
|
|
config: null,
|
|
metadata: null,
|
|
runtimeServices: storybookProjectWorkspaces[0]!.runtimeServices,
|
|
createdAt: recent(90),
|
|
updatedAt: recent(3),
|
|
},
|
|
{
|
|
id: "execution-workspace-cleanup",
|
|
companyId: "company-storybook",
|
|
projectId: "project-board-ui",
|
|
projectWorkspaceId: "workspace-release-local",
|
|
sourceIssueId: "issue-storybook-8",
|
|
mode: "isolated_workspace",
|
|
strategyType: "git_worktree",
|
|
name: "PAP-1608 release smoke cleanup",
|
|
status: "cleanup_failed",
|
|
cwd: `${storybookWorktreeRoot}/PAP-1608-release-smoke-cleanup`,
|
|
repoUrl: "https://github.com/paperclipai/paperclip",
|
|
baseRef: "master",
|
|
branchName: "PAP-1608-release-smoke-cleanup",
|
|
providerType: "git_worktree",
|
|
providerRef: null,
|
|
derivedFromExecutionWorkspaceId: null,
|
|
lastUsedAt: recent(120),
|
|
openedAt: recent(260),
|
|
closedAt: recent(118),
|
|
cleanupEligibleAt: recent(115),
|
|
cleanupReason: "release smoke finished but the local worktree still has generated artifacts",
|
|
config: {
|
|
provisionCommand: null,
|
|
teardownCommand: "pnpm dev:stop && rm -rf ui/storybook-static",
|
|
cleanupCommand: null,
|
|
workspaceRuntime: storybookWorkspaceRuntime,
|
|
desiredState: "stopped",
|
|
serviceStates: { storybook: "stopped" },
|
|
},
|
|
metadata: { dirtyEntryCount: 3 },
|
|
runtimeServices: [
|
|
createRuntimeService({
|
|
id: "service-cleanup-storybook",
|
|
projectWorkspaceId: "workspace-release-local",
|
|
executionWorkspaceId: "execution-workspace-cleanup",
|
|
issueId: "issue-storybook-8",
|
|
scopeId: "execution-workspace-cleanup",
|
|
status: "failed",
|
|
healthStatus: "unhealthy",
|
|
url: "http://localhost:6007",
|
|
port: 6007,
|
|
lastUsedAt: recent(130),
|
|
startedAt: recent(210),
|
|
stoppedAt: recent(125),
|
|
updatedAt: recent(120),
|
|
}),
|
|
],
|
|
createdAt: recent(260),
|
|
updatedAt: recent(120),
|
|
},
|
|
];
|
|
|
|
function createProject(overrides: Partial<Project> = {}): Project {
|
|
const id = overrides.id ?? "project-board-ui";
|
|
return {
|
|
id,
|
|
companyId: "company-storybook",
|
|
urlKey: "board-ui",
|
|
goalId: "goal-company",
|
|
goalIds: ["goal-company", "goal-board-ux"],
|
|
goals: storybookGoals
|
|
.filter((goal) => goal.id === "goal-company" || goal.id === "goal-board-ux")
|
|
.map(({ id, title }) => ({ id, title })),
|
|
name: "Board UI",
|
|
description: "Navigation, command, and operator layout polish.",
|
|
status: "in_progress",
|
|
leadAgentId: "agent-codex",
|
|
targetDate: "2026-04-30",
|
|
color: "#0f766e",
|
|
env: null,
|
|
pauseReason: null,
|
|
pausedAt: null,
|
|
executionWorkspacePolicy: {
|
|
enabled: true,
|
|
defaultMode: "isolated_workspace",
|
|
allowIssueOverride: true,
|
|
defaultProjectWorkspaceId: "workspace-board-ui",
|
|
workspaceStrategy: {
|
|
type: "git_worktree",
|
|
baseRef: "master",
|
|
branchTemplate: "{issueIdentifier}-{slug}",
|
|
worktreeParentDir: storybookWorktreeRoot,
|
|
provisionCommand: null,
|
|
teardownCommand: null,
|
|
},
|
|
workspaceRuntime: null,
|
|
branchPolicy: null,
|
|
pullRequestPolicy: null,
|
|
runtimePolicy: null,
|
|
cleanupPolicy: null,
|
|
},
|
|
codebase: {
|
|
workspaceId: "workspace-board-ui",
|
|
repoUrl: "https://github.com/paperclipai/paperclip",
|
|
repoRef: "master",
|
|
defaultRef: "master",
|
|
repoName: "paperclip",
|
|
localFolder: storybookRepoRoot,
|
|
managedFolder: ".paperclip/worktrees/storybook",
|
|
effectiveLocalFolder: storybookRepoRoot,
|
|
origin: "local_folder",
|
|
},
|
|
workspaces: storybookProjectWorkspaces,
|
|
primaryWorkspace: storybookProjectWorkspaces[0]!,
|
|
archivedAt: null,
|
|
createdAt: recent(18_000),
|
|
updatedAt: recent(12),
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
export const storybookProjects: Project[] = [
|
|
createProject(),
|
|
createProject({
|
|
id: "project-runtime",
|
|
urlKey: "agent-runtime",
|
|
name: "Agent Runtime",
|
|
description: "Heartbeat, adapters, and execution trace work.",
|
|
status: "planned",
|
|
leadAgentId: "agent-cto",
|
|
color: "#2563eb",
|
|
updatedAt: recent(60),
|
|
}),
|
|
createProject({
|
|
id: "project-budget",
|
|
urlKey: "budget-guardrails",
|
|
name: "Budget Guardrails",
|
|
description: "Hard-stop and approval flow review surfaces.",
|
|
status: "in_progress",
|
|
leadAgentId: "agent-qa",
|
|
color: "#f59e0b",
|
|
pauseReason: "budget",
|
|
pausedAt: recent(90),
|
|
updatedAt: recent(90),
|
|
}),
|
|
createProject({
|
|
id: "project-archived-import",
|
|
urlKey: "archived-import-wizard",
|
|
name: "Archived Import Wizard",
|
|
description: "Preserved for audit after the import workflow moved into company packages.",
|
|
status: "cancelled",
|
|
leadAgentId: null,
|
|
goalId: "goal-archived-import",
|
|
goalIds: ["goal-archived-import"],
|
|
goals: [{ id: "goal-archived-import", title: "Retire old import wizard" }],
|
|
color: "#64748b",
|
|
workspaces: [],
|
|
primaryWorkspace: null,
|
|
codebase: {
|
|
workspaceId: null,
|
|
repoUrl: null,
|
|
repoRef: null,
|
|
defaultRef: null,
|
|
repoName: null,
|
|
localFolder: null,
|
|
managedFolder: "",
|
|
effectiveLocalFolder: "Not configured",
|
|
origin: "local_folder",
|
|
},
|
|
executionWorkspacePolicy: {
|
|
enabled: false,
|
|
defaultMode: "shared_workspace",
|
|
allowIssueOverride: false,
|
|
defaultProjectWorkspaceId: null,
|
|
workspaceStrategy: null,
|
|
workspaceRuntime: null,
|
|
branchPolicy: null,
|
|
pullRequestPolicy: null,
|
|
runtimePolicy: null,
|
|
cleanupPolicy: null,
|
|
},
|
|
archivedAt: recent(2_400),
|
|
updatedAt: recent(2_400),
|
|
}),
|
|
];
|
|
|
|
export function createIssue(overrides: Partial<Issue> = {}): Issue {
|
|
return {
|
|
id: "issue-storybook-1",
|
|
companyId: "company-storybook",
|
|
projectId: "project-board-ui",
|
|
projectWorkspaceId: "workspace-board-ui",
|
|
goalId: "goal-company",
|
|
parentId: null,
|
|
title: "Create super-detailed storybooks for the project",
|
|
description: "Set up Storybook and move UX review surfaces into stories.",
|
|
status: "in_progress",
|
|
priority: "high",
|
|
assigneeAgentId: "agent-codex",
|
|
assigneeUserId: null,
|
|
checkoutRunId: "run-storybook",
|
|
executionRunId: "run-storybook",
|
|
executionAgentNameKey: "codexcoder",
|
|
executionLockedAt: recent(28),
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
issueNumber: 1641,
|
|
identifier: "PAP-1641",
|
|
requestDepth: 0,
|
|
billingCode: "product",
|
|
assigneeAdapterOverrides: null,
|
|
executionWorkspaceId: "execution-workspace-storybook",
|
|
executionWorkspacePreference: "project",
|
|
executionWorkspaceSettings: null,
|
|
startedAt: recent(28),
|
|
completedAt: null,
|
|
cancelledAt: null,
|
|
hiddenAt: null,
|
|
labelIds: ["label-ui", "label-docs"],
|
|
labels: labelsFor(["label-ui", "label-docs"]),
|
|
blockedBy: [],
|
|
blocks: [],
|
|
planDocument: null,
|
|
documentSummaries: [],
|
|
legacyPlanDocument: null,
|
|
project: storybookProjects[0]!,
|
|
goal: null,
|
|
currentExecutionWorkspace: storybookExecutionWorkspaces[0]!,
|
|
workProducts: [],
|
|
mentionedProjects: [],
|
|
myLastTouchAt: recent(8),
|
|
lastExternalCommentAt: recent(70),
|
|
lastActivityAt: recent(3),
|
|
isUnreadForMe: true,
|
|
createdAt: recent(90),
|
|
updatedAt: recent(3),
|
|
...overrides,
|
|
workMode: overrides.workMode ?? "standard",
|
|
};
|
|
}
|
|
|
|
export const storybookIssues: Issue[] = [
|
|
createIssue(),
|
|
createIssue({
|
|
id: "issue-storybook-2",
|
|
title: "Add budget hard-stop incident review",
|
|
description: "Trace why a hard stop paused the agent and add a board-facing incident summary.",
|
|
status: "blocked",
|
|
priority: "critical",
|
|
assigneeAgentId: "agent-qa",
|
|
checkoutRunId: null,
|
|
executionRunId: null,
|
|
executionLockedAt: null,
|
|
startedAt: null,
|
|
identifier: "PAP-1528",
|
|
issueNumber: 1528,
|
|
billingCode: "reliability",
|
|
projectId: "project-budget",
|
|
projectWorkspaceId: null,
|
|
labelIds: ["label-risk", "label-backend"],
|
|
labels: labelsFor(["label-risk", "label-backend"]),
|
|
blockedBy: [
|
|
{
|
|
id: "issue-storybook-7",
|
|
identifier: "PAP-1591",
|
|
title: "Confirm project budget override policy",
|
|
status: "in_review",
|
|
priority: "high",
|
|
assigneeAgentId: null,
|
|
assigneeUserId: "user-board",
|
|
},
|
|
],
|
|
lastActivityAt: recent(18),
|
|
}),
|
|
createIssue({
|
|
id: "issue-storybook-3",
|
|
title: "QA invite flow on authenticated private mode",
|
|
status: "in_review",
|
|
priority: "medium",
|
|
assigneeAgentId: null,
|
|
assigneeUserId: "user-board",
|
|
checkoutRunId: null,
|
|
executionRunId: null,
|
|
executionLockedAt: null,
|
|
identifier: "PAP-1602",
|
|
issueNumber: 1602,
|
|
completedAt: null,
|
|
lastActivityAt: recent(49),
|
|
isUnreadForMe: false,
|
|
}),
|
|
createIssue({
|
|
id: "issue-storybook-4",
|
|
parentId: "issue-storybook-1",
|
|
title: "Extract issue row density fixtures",
|
|
description: "Create fixture-backed rows for unread, selected, nested, and grouped issue management views.",
|
|
status: "todo",
|
|
priority: "medium",
|
|
assigneeAgentId: "agent-codex",
|
|
checkoutRunId: null,
|
|
executionRunId: null,
|
|
executionLockedAt: null,
|
|
startedAt: null,
|
|
identifier: "PAP-1668",
|
|
issueNumber: 1668,
|
|
labelIds: ["label-ui"],
|
|
labels: labelsFor(["label-ui"]),
|
|
lastActivityAt: recent(31),
|
|
isUnreadForMe: true,
|
|
}),
|
|
createIssue({
|
|
id: "issue-storybook-5",
|
|
parentId: "issue-storybook-1",
|
|
title: "Review document editor empty states",
|
|
description: "Validate plan and notes documents in issue detail before handing the Storybook preview to QA.",
|
|
status: "done",
|
|
priority: "low",
|
|
assigneeAgentId: "agent-qa",
|
|
checkoutRunId: null,
|
|
executionRunId: "run-storybook-qa",
|
|
executionLockedAt: null,
|
|
completedAt: recent(22),
|
|
identifier: "PAP-1669",
|
|
issueNumber: 1669,
|
|
labelIds: ["label-docs"],
|
|
labels: labelsFor(["label-docs"]),
|
|
lastActivityAt: recent(22),
|
|
isUnreadForMe: false,
|
|
}),
|
|
createIssue({
|
|
id: "issue-storybook-6",
|
|
title: "Publish static Storybook preview",
|
|
description: "Build the static preview and attach the generated artifact to the parent issue.",
|
|
status: "todo",
|
|
priority: "high",
|
|
assigneeAgentId: null,
|
|
assigneeUserId: null,
|
|
checkoutRunId: null,
|
|
executionRunId: null,
|
|
executionLockedAt: null,
|
|
startedAt: null,
|
|
identifier: "PAP-1670",
|
|
issueNumber: 1670,
|
|
labelIds: ["label-ui", "label-risk"],
|
|
labels: labelsFor(["label-ui", "label-risk"]),
|
|
lastActivityAt: recent(64),
|
|
isUnreadForMe: false,
|
|
}),
|
|
createIssue({
|
|
id: "issue-storybook-7",
|
|
title: "Confirm project budget override policy",
|
|
description: "Board review needed before increasing the project budget for long-running browser verification.",
|
|
status: "in_review",
|
|
priority: "high",
|
|
assigneeAgentId: null,
|
|
assigneeUserId: "user-board",
|
|
checkoutRunId: null,
|
|
executionRunId: null,
|
|
executionLockedAt: null,
|
|
startedAt: null,
|
|
identifier: "PAP-1591",
|
|
issueNumber: 1591,
|
|
billingCode: "governance",
|
|
projectId: "project-budget",
|
|
projectWorkspaceId: null,
|
|
labelIds: ["label-risk"],
|
|
labels: labelsFor(["label-risk"]),
|
|
lastActivityAt: recent(85),
|
|
isUnreadForMe: false,
|
|
}),
|
|
createIssue({
|
|
id: "issue-storybook-8",
|
|
title: "Clean up release smoke worktree",
|
|
description: "Close the isolated release smoke workspace after static preview review.",
|
|
status: "blocked",
|
|
priority: "medium",
|
|
assigneeAgentId: "agent-codex",
|
|
checkoutRunId: null,
|
|
executionRunId: "run-release-smoke-cleanup",
|
|
executionLockedAt: null,
|
|
startedAt: recent(260),
|
|
identifier: "PAP-1608",
|
|
issueNumber: 1608,
|
|
projectId: "project-board-ui",
|
|
projectWorkspaceId: "workspace-release-local",
|
|
executionWorkspaceId: "execution-workspace-cleanup",
|
|
labelIds: ["label-ui", "label-risk"],
|
|
labels: labelsFor(["label-ui", "label-risk"]),
|
|
lastActivityAt: recent(120),
|
|
isUnreadForMe: false,
|
|
}),
|
|
];
|
|
|
|
export const storybookIssueDocuments: IssueDocument[] = [
|
|
{
|
|
id: "document-plan-storybook",
|
|
companyId: "company-storybook",
|
|
issueId: "issue-storybook-1",
|
|
key: "plan",
|
|
title: "Plan",
|
|
format: "markdown",
|
|
body: [
|
|
"# Plan",
|
|
"",
|
|
"- Add issue-management stories for list, filters, detail, documents, runs, and workspace cards.",
|
|
"- Use existing product components instead of mock-only approximations.",
|
|
"- Verify the Storybook build after the fixture expansion.",
|
|
].join("\n"),
|
|
latestRevisionId: "revision-plan-3",
|
|
latestRevisionNumber: 3,
|
|
createdByAgentId: "agent-codex",
|
|
createdByUserId: null,
|
|
updatedByAgentId: "agent-codex",
|
|
updatedByUserId: null,
|
|
lockedAt: null,
|
|
lockedByAgentId: null,
|
|
lockedByUserId: null,
|
|
createdAt: recent(80),
|
|
updatedAt: recent(8),
|
|
},
|
|
{
|
|
id: "document-notes-storybook",
|
|
companyId: "company-storybook",
|
|
issueId: "issue-storybook-1",
|
|
key: "notes",
|
|
title: "Review Notes",
|
|
format: "markdown",
|
|
body: [
|
|
"# Review Notes",
|
|
"",
|
|
"- The issue list needs group headers and dense trailing columns.",
|
|
"- The filters popover should show selected status, priority, and assignee filters.",
|
|
"- Workspace copy must expose branch, path, and runtime status.",
|
|
].join("\n"),
|
|
latestRevisionId: "revision-notes-1",
|
|
latestRevisionNumber: 1,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
updatedByAgentId: null,
|
|
updatedByUserId: "user-board",
|
|
lockedAt: null,
|
|
lockedByAgentId: null,
|
|
lockedByUserId: null,
|
|
createdAt: recent(55),
|
|
updatedAt: recent(12),
|
|
},
|
|
];
|
|
|
|
export const storybookContinuationHandoff: IssueDocument = {
|
|
id: "document-continuation-storybook",
|
|
companyId: "company-storybook",
|
|
issueId: "issue-storybook-1",
|
|
key: "continuation_summary",
|
|
title: "Continuation handoff",
|
|
format: "markdown",
|
|
body: [
|
|
"Current state: issue-management stories have the fixture surface mapped.",
|
|
"",
|
|
"Next action: run the Storybook build, inspect the issue management story, then request QA visual review if the build passes.",
|
|
"",
|
|
"Important files: `ui/storybook/stories/issue-management.stories.tsx` and `ui/storybook/fixtures/paperclipData.ts`.",
|
|
].join("\n"),
|
|
latestRevisionId: "revision-continuation-1",
|
|
latestRevisionNumber: 1,
|
|
createdByAgentId: "agent-codex",
|
|
createdByUserId: null,
|
|
updatedByAgentId: "agent-codex",
|
|
updatedByUserId: null,
|
|
lockedAt: null,
|
|
lockedByAgentId: null,
|
|
lockedByUserId: null,
|
|
createdAt: recent(18),
|
|
updatedAt: recent(5),
|
|
};
|
|
|
|
export const storybookIssueRuns: RunForIssue[] = [
|
|
{
|
|
runId: "run-storybook",
|
|
status: "running",
|
|
agentId: "agent-codex",
|
|
adapterType: "codex_local",
|
|
startedAt: recent(28).toISOString(),
|
|
finishedAt: null,
|
|
createdAt: recent(28).toISOString(),
|
|
invocationSource: "manual",
|
|
usageJson: { costCents: 142, inputTokens: 38400, outputTokens: 7200 },
|
|
resultJson: null,
|
|
logBytes: 62_400,
|
|
livenessState: null,
|
|
livenessReason: null,
|
|
continuationAttempt: 1,
|
|
lastUsefulActionAt: recent(3).toISOString(),
|
|
nextAction: "Finish the issue-management Storybook and verify the static build.",
|
|
},
|
|
{
|
|
runId: "run-storybook-qa",
|
|
status: "succeeded",
|
|
agentId: "agent-qa",
|
|
adapterType: "claude_local",
|
|
startedAt: recent(110).toISOString(),
|
|
finishedAt: recent(94).toISOString(),
|
|
createdAt: recent(110).toISOString(),
|
|
invocationSource: "manual",
|
|
usageJson: { costCents: 38, inputTokens: 12200, outputTokens: 1900 },
|
|
resultJson: { stopReason: "completed" },
|
|
logBytes: 18_400,
|
|
livenessState: "advanced",
|
|
livenessReason: "Verified the document editor empty state and left concrete screenshot notes.",
|
|
continuationAttempt: 0,
|
|
lastUsefulActionAt: recent(96).toISOString(),
|
|
nextAction: "Re-run after final story fixture additions land.",
|
|
},
|
|
{
|
|
runId: "run-storybook-plan",
|
|
status: "succeeded",
|
|
agentId: "agent-codex",
|
|
adapterType: "codex_local",
|
|
startedAt: recent(210).toISOString(),
|
|
finishedAt: recent(196).toISOString(),
|
|
createdAt: recent(210).toISOString(),
|
|
invocationSource: "scheduler",
|
|
usageJson: { costCents: 24, inputTokens: 9100, outputTokens: 1100 },
|
|
resultJson: { stopReason: "completed" },
|
|
logBytes: 9800,
|
|
livenessState: "plan_only",
|
|
livenessReason: "Identified Storybook coverage gaps but did not edit files in that run.",
|
|
continuationAttempt: 0,
|
|
lastUsefulActionAt: null,
|
|
nextAction: "Implement issue-management stories in the next heartbeat.",
|
|
},
|
|
];
|
|
|
|
export const storybookApprovals: Approval[] = [
|
|
{
|
|
id: "approval-hire-designer",
|
|
companyId: "company-storybook",
|
|
type: "hire_agent",
|
|
requestedByAgentId: "agent-cto",
|
|
requestedByUserId: null,
|
|
status: "pending",
|
|
payload: {
|
|
name: "DesignSystemCoder",
|
|
role: "designer",
|
|
title: "Design System Engineer",
|
|
icon: "sparkles",
|
|
adapterType: "codex_local",
|
|
capabilities: "Owns component quality, visual regression stories, and design-system consolidation.",
|
|
desiredSkills: ["frontend-design", "web-design-guidelines"],
|
|
},
|
|
decisionNote: null,
|
|
decidedByUserId: null,
|
|
decidedAt: null,
|
|
createdAt: recent(42),
|
|
updatedAt: recent(42),
|
|
},
|
|
{
|
|
id: "approval-budget",
|
|
companyId: "company-storybook",
|
|
type: "budget_override_required",
|
|
requestedByAgentId: "agent-codex",
|
|
requestedByUserId: null,
|
|
status: "revision_requested",
|
|
payload: {
|
|
scopeName: "Paperclip App",
|
|
scopeType: "project",
|
|
windowKind: "calendar_month_utc",
|
|
metric: "billed_cents",
|
|
budgetAmount: 120_000,
|
|
observedAmount: 131_400,
|
|
guidance: "Raise the project budget only after current release smoke checks are green.",
|
|
},
|
|
decisionNote: "Need a tighter verification list before approving more spend.",
|
|
decidedByUserId: "user-board",
|
|
decidedAt: recent(12),
|
|
createdAt: recent(75),
|
|
updatedAt: recent(12),
|
|
},
|
|
{
|
|
id: "approval-board",
|
|
companyId: "company-storybook",
|
|
type: "request_board_approval",
|
|
requestedByAgentId: "agent-cto",
|
|
requestedByUserId: null,
|
|
status: "approved",
|
|
payload: {
|
|
title: "Publish the Storybook preview for design review",
|
|
summary: "Build the static Storybook and attach the generated URL to the release issue.",
|
|
recommendedAction: "Approve publishing the preview for internal board review.",
|
|
nextActionOnApproval: "Run build-storybook, upload the static artifact, and request QA visual review.",
|
|
risks: [
|
|
"Stories may expose stale fixture copy if not maintained with UI changes.",
|
|
"Preview screenshots can hide responsive regressions unless mobile viewports are checked.",
|
|
],
|
|
},
|
|
decisionNote: "Approved for internal-only review.",
|
|
decidedByUserId: "user-board",
|
|
decidedAt: recent(4),
|
|
createdAt: recent(55),
|
|
updatedAt: recent(4),
|
|
},
|
|
];
|
|
|
|
export const storybookBudgetSummaries: BudgetPolicySummary[] = [
|
|
{
|
|
policyId: "budget-company-ok",
|
|
companyId: "company-storybook",
|
|
scopeType: "company",
|
|
scopeId: "company-storybook",
|
|
scopeName: "Paperclip Storybook",
|
|
metric: "billed_cents",
|
|
windowKind: "calendar_month_utc",
|
|
amount: 250_000,
|
|
observedAmount: 67_500,
|
|
remainingAmount: 182_500,
|
|
utilizationPercent: 27,
|
|
warnPercent: 80,
|
|
hardStopEnabled: true,
|
|
notifyEnabled: true,
|
|
isActive: true,
|
|
status: "ok",
|
|
paused: false,
|
|
pauseReason: null,
|
|
windowStart: new Date("2026-04-01T00:00:00.000Z"),
|
|
windowEnd: new Date("2026-05-01T00:00:00.000Z"),
|
|
},
|
|
{
|
|
policyId: "budget-project-warning",
|
|
companyId: "company-storybook",
|
|
scopeType: "project",
|
|
scopeId: "project-board-ui",
|
|
scopeName: "Paperclip App",
|
|
metric: "billed_cents",
|
|
windowKind: "calendar_month_utc",
|
|
amount: 120_000,
|
|
observedAmount: 103_100,
|
|
remainingAmount: 16_900,
|
|
utilizationPercent: 86,
|
|
warnPercent: 80,
|
|
hardStopEnabled: true,
|
|
notifyEnabled: true,
|
|
isActive: true,
|
|
status: "warning",
|
|
paused: false,
|
|
pauseReason: null,
|
|
windowStart: new Date("2026-04-01T00:00:00.000Z"),
|
|
windowEnd: new Date("2026-05-01T00:00:00.000Z"),
|
|
},
|
|
{
|
|
policyId: "budget-agent-hard-stop",
|
|
companyId: "company-storybook",
|
|
scopeType: "agent",
|
|
scopeId: "agent-codex",
|
|
scopeName: "CodexCoder",
|
|
metric: "billed_cents",
|
|
windowKind: "calendar_month_utc",
|
|
amount: 40_000,
|
|
observedAmount: 43_200,
|
|
remainingAmount: 0,
|
|
utilizationPercent: 108,
|
|
warnPercent: 80,
|
|
hardStopEnabled: true,
|
|
notifyEnabled: true,
|
|
isActive: true,
|
|
status: "hard_stop",
|
|
paused: true,
|
|
pauseReason: "budget",
|
|
windowStart: new Date("2026-04-01T00:00:00.000Z"),
|
|
windowEnd: new Date("2026-05-01T00:00:00.000Z"),
|
|
},
|
|
];
|
|
|
|
export const storybookActivityEvents: ActivityEvent[] = [
|
|
{
|
|
id: "activity-1",
|
|
companyId: "company-storybook",
|
|
actorType: "agent",
|
|
actorId: "agent-codex",
|
|
action: "issue.status_changed",
|
|
entityType: "issue",
|
|
entityId: "issue-storybook-1",
|
|
agentId: "agent-codex",
|
|
runId: "run-storybook",
|
|
details: { from: "todo", to: "in_progress" },
|
|
createdAt: recent(28),
|
|
},
|
|
{
|
|
id: "activity-2",
|
|
companyId: "company-storybook",
|
|
actorType: "user",
|
|
actorId: "user-board",
|
|
action: "approval.revision_requested",
|
|
entityType: "approval",
|
|
entityId: "approval-budget",
|
|
agentId: null,
|
|
runId: null,
|
|
details: { type: "budget_override_required" },
|
|
createdAt: recent(12),
|
|
},
|
|
{
|
|
id: "activity-3",
|
|
companyId: "company-storybook",
|
|
actorType: "system",
|
|
actorId: "system",
|
|
action: "budget.hard_stop",
|
|
entityType: "agent",
|
|
entityId: "agent-codex",
|
|
agentId: "agent-codex",
|
|
runId: null,
|
|
details: { observedAmount: 43_200, budgetAmount: 40_000 },
|
|
createdAt: recent(7),
|
|
},
|
|
];
|
|
|
|
export const storybookEntityNameMap = new Map<string, string>([
|
|
["issue:issue-storybook-1", "PAP-1641"],
|
|
["issue:issue-storybook-2", "PAP-1528"],
|
|
["issue:issue-storybook-3", "PAP-1602"],
|
|
["issue:issue-storybook-4", "PAP-1668"],
|
|
["issue:issue-storybook-5", "PAP-1669"],
|
|
["issue:issue-storybook-6", "PAP-1670"],
|
|
["issue:issue-storybook-7", "PAP-1591"],
|
|
["approval:approval-budget", "Budget override"],
|
|
["agent:agent-codex", "CodexCoder"],
|
|
["agent:agent-qa", "QAChecker"],
|
|
["agent:agent-cto", "CTO"],
|
|
]);
|
|
|
|
export const storybookEntityTitleMap = new Map<string, string>([
|
|
["issue:issue-storybook-1", "Create super-detailed storybooks for the project"],
|
|
["issue:issue-storybook-2", "Add budget hard-stop incident review"],
|
|
["issue:issue-storybook-3", "QA invite flow on authenticated private mode"],
|
|
["issue:issue-storybook-4", "Extract issue row density fixtures"],
|
|
["issue:issue-storybook-5", "Review document editor empty states"],
|
|
["issue:issue-storybook-6", "Publish static Storybook preview"],
|
|
["issue:issue-storybook-7", "Confirm project budget override policy"],
|
|
]);
|
|
|
|
export const storybookSidebarBadges: SidebarBadges = {
|
|
inbox: 7,
|
|
approvals: 2,
|
|
failedRuns: 1,
|
|
joinRequests: 1,
|
|
};
|
|
|
|
export const storybookDashboardSummary: DashboardSummary = {
|
|
companyId: "company-storybook",
|
|
agents: {
|
|
active: 3,
|
|
running: 1,
|
|
paused: 0,
|
|
error: 0,
|
|
},
|
|
tasks: {
|
|
open: 12,
|
|
inProgress: 4,
|
|
blocked: 1,
|
|
done: 36,
|
|
},
|
|
costs: {
|
|
monthSpendCents: 67_500,
|
|
monthBudgetCents: 250_000,
|
|
monthUtilizationPercent: 27,
|
|
},
|
|
pendingApprovals: 2,
|
|
budgets: {
|
|
activeIncidents: 1,
|
|
pendingApprovals: 1,
|
|
pausedAgents: 0,
|
|
pausedProjects: 1,
|
|
},
|
|
runActivity: [
|
|
{ date: "2026-04-07", succeeded: 4, failed: 0, other: 1, total: 5 },
|
|
{ date: "2026-04-08", succeeded: 5, failed: 1, other: 0, total: 6 },
|
|
{ date: "2026-04-09", succeeded: 3, failed: 0, other: 1, total: 4 },
|
|
{ date: "2026-04-10", succeeded: 6, failed: 0, other: 0, total: 6 },
|
|
{ date: "2026-04-11", succeeded: 4, failed: 1, other: 0, total: 5 },
|
|
{ date: "2026-04-12", succeeded: 2, failed: 0, other: 1, total: 3 },
|
|
{ date: "2026-04-13", succeeded: 5, failed: 0, other: 1, total: 6 },
|
|
{ date: "2026-04-14", succeeded: 6, failed: 1, other: 0, total: 7 },
|
|
{ date: "2026-04-15", succeeded: 4, failed: 0, other: 1, total: 5 },
|
|
{ date: "2026-04-16", succeeded: 7, failed: 0, other: 0, total: 7 },
|
|
{ date: "2026-04-17", succeeded: 6, failed: 1, other: 0, total: 7 },
|
|
{ date: "2026-04-18", succeeded: 3, failed: 0, other: 1, total: 4 },
|
|
{ date: "2026-04-19", succeeded: 5, failed: 0, other: 1, total: 6 },
|
|
{ date: "2026-04-20", succeeded: 4, failed: 0, other: 2, total: 6 },
|
|
],
|
|
};
|
|
|
|
export const storybookLiveRuns: LiveRunForIssue[] = [
|
|
{
|
|
id: "run-storybook",
|
|
status: "running",
|
|
invocationSource: "manual",
|
|
triggerDetail: "issue_assigned",
|
|
startedAt: recent(28).toISOString(),
|
|
finishedAt: null,
|
|
createdAt: recent(28).toISOString(),
|
|
agentId: "agent-codex",
|
|
agentName: "CodexCoder",
|
|
adapterType: "codex_local",
|
|
issueId: "issue-storybook-1",
|
|
livenessState: "advanced",
|
|
livenessReason: null,
|
|
continuationAttempt: 0,
|
|
lastUsefulActionAt: recent(3).toISOString(),
|
|
nextAction: "Build fixture-backed navigation stories",
|
|
},
|
|
];
|
|
|
|
export const storybookSecretProviders: SecretProviderDescriptor[] = [
|
|
{ id: "local_encrypted", label: "Local encrypted", requiresExternalRef: false },
|
|
{ id: "aws_secrets_manager", label: "AWS Secrets Manager", requiresExternalRef: false },
|
|
{ id: "gcp_secret_manager", label: "GCP Secret Manager", requiresExternalRef: false },
|
|
{ id: "vault", label: "HashiCorp Vault", requiresExternalRef: false },
|
|
];
|
|
|
|
export const storybookSecretProviderConfigs: CompanySecretProviderConfig[] = [
|
|
{
|
|
id: "provider-config-local",
|
|
companyId: "company-storybook",
|
|
provider: "local_encrypted",
|
|
displayName: "Local encrypted default",
|
|
status: "ready",
|
|
isDefault: true,
|
|
config: { backupReminderAcknowledged: true },
|
|
healthStatus: "ready",
|
|
healthCheckedAt: recent(45),
|
|
healthMessage: "Local encrypted provider is healthy.",
|
|
healthDetails: null,
|
|
disabledAt: null,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
createdAt: recent(2_400),
|
|
updatedAt: recent(45),
|
|
},
|
|
{
|
|
id: "provider-config-aws-prod",
|
|
companyId: "company-storybook",
|
|
provider: "aws_secrets_manager",
|
|
displayName: "AWS production",
|
|
status: "warning",
|
|
isDefault: false,
|
|
config: {
|
|
region: "us-east-1",
|
|
namespace: "prod-use1",
|
|
secretNamePrefix: "paperclip",
|
|
kmsKeyId: "alias/paperclip-secrets",
|
|
ownerTag: "platform",
|
|
environmentTag: "production",
|
|
},
|
|
healthStatus: "warning",
|
|
healthCheckedAt: recent(18),
|
|
healthMessage: "Connected; KMS key rotation policy not yet enforced.",
|
|
healthDetails: {
|
|
code: "kms_rotation_policy",
|
|
message: "Connected; KMS key rotation policy not yet enforced.",
|
|
guidance: ["Enable automatic key rotation before using this vault for production agents."],
|
|
},
|
|
disabledAt: null,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
createdAt: recent(1_800),
|
|
updatedAt: recent(18),
|
|
},
|
|
];
|
|
|
|
export const storybookSecretProviderDiscoveryPreview: SecretProviderConfigDiscoveryPreviewResult = {
|
|
provider: "aws_secrets_manager",
|
|
nextToken: null,
|
|
sampledSecretCount: 6,
|
|
skippedForeignPaperclipSampleCount: 1,
|
|
warnings: ["Skipped 1 Paperclip-managed AWS secret from a different deployment namespace."],
|
|
candidates: [
|
|
{
|
|
provider: "aws_secrets_manager",
|
|
displayName: "AWS production",
|
|
config: {
|
|
region: "us-east-1",
|
|
namespace: "prod-use1",
|
|
secretNamePrefix: "paperclip",
|
|
kmsKeyId: "alias/paperclip-secrets",
|
|
ownerTag: "platform",
|
|
environmentTag: "production",
|
|
},
|
|
sampleCount: 5,
|
|
samples: [
|
|
{
|
|
name: "paperclip/prod-use1/company-storybook/openai_api_key",
|
|
hasKmsKey: true,
|
|
tagKeys: ["paperclip:managed-by", "paperclip:environment", "paperclip:provider-owner"],
|
|
},
|
|
],
|
|
signals: {
|
|
namespace: "prod-use1",
|
|
secretNamePrefix: "paperclip",
|
|
environmentTag: "production",
|
|
ownerTag: "platform",
|
|
kmsKeyId: "alias/paperclip-secrets",
|
|
hasKmsKey: true,
|
|
sampleCount: 5,
|
|
paperclipManagedSampleCount: 5,
|
|
skippedForeignPaperclipSampleCount: 1,
|
|
},
|
|
warnings: [],
|
|
},
|
|
],
|
|
};
|
|
|
|
export const storybookSecrets: CompanySecret[] = [
|
|
{
|
|
id: "secret-openai",
|
|
companyId: "company-storybook",
|
|
key: "openai_api_key",
|
|
name: "OPENAI_API_KEY",
|
|
provider: "local_encrypted",
|
|
status: "active",
|
|
managedMode: "paperclip_managed",
|
|
externalRef: null,
|
|
providerConfigId: null,
|
|
providerMetadata: null,
|
|
latestVersion: 3,
|
|
description: "OpenAI API key shared by all model adapters.",
|
|
lastResolvedAt: recent(12),
|
|
lastRotatedAt: new Date("2026-04-15T09:30:00.000Z"),
|
|
deletedAt: null,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
createdAt: new Date("2026-03-01T10:00:00.000Z"),
|
|
updatedAt: recent(12),
|
|
},
|
|
{
|
|
id: "secret-aws-prod",
|
|
companyId: "company-storybook",
|
|
key: "prod_aws_deploy",
|
|
name: "PROD_AWS_DEPLOY_KEY",
|
|
provider: "aws_secrets_manager",
|
|
status: "active",
|
|
managedMode: "external_reference",
|
|
externalRef: "arn:aws:secretsmanager:us-east-1:123456789012:secret:paperclip/prod/aws-deploy-AbCdEf",
|
|
providerConfigId: null,
|
|
providerMetadata: null,
|
|
latestVersion: 2,
|
|
description: "Deploy key for the prod ECS rollout pipeline.",
|
|
lastResolvedAt: recent(180),
|
|
lastRotatedAt: new Date("2026-04-22T14:00:00.000Z"),
|
|
deletedAt: null,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
createdAt: new Date("2026-02-01T10:00:00.000Z"),
|
|
updatedAt: recent(180),
|
|
},
|
|
{
|
|
id: "secret-github",
|
|
companyId: "company-storybook",
|
|
key: "github_app_pem",
|
|
name: "GITHUB_APP_PEM",
|
|
provider: "local_encrypted",
|
|
status: "disabled",
|
|
managedMode: "paperclip_managed",
|
|
externalRef: null,
|
|
providerConfigId: null,
|
|
providerMetadata: null,
|
|
latestVersion: 1,
|
|
description: "Disabled until GitHub App reinstall is approved.",
|
|
lastResolvedAt: new Date("2026-03-30T08:11:00.000Z"),
|
|
lastRotatedAt: null,
|
|
deletedAt: null,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
createdAt: new Date("2026-03-15T10:00:00.000Z"),
|
|
updatedAt: new Date("2026-04-21T11:30:00.000Z"),
|
|
},
|
|
{
|
|
id: "secret-stripe-archived",
|
|
companyId: "company-storybook",
|
|
key: "stripe_legacy",
|
|
name: "STRIPE_LEGACY",
|
|
provider: "vault",
|
|
status: "archived",
|
|
managedMode: "external_reference",
|
|
externalRef: "secret/data/payments/stripe-legacy",
|
|
providerConfigId: null,
|
|
providerMetadata: null,
|
|
latestVersion: 4,
|
|
description: "Migrated to managed billing service. Kept for backfill jobs.",
|
|
lastResolvedAt: new Date("2026-02-25T08:11:00.000Z"),
|
|
lastRotatedAt: new Date("2026-02-20T08:11:00.000Z"),
|
|
deletedAt: null,
|
|
createdByAgentId: null,
|
|
createdByUserId: "user-board",
|
|
createdAt: new Date("2025-12-01T10:00:00.000Z"),
|
|
updatedAt: new Date("2026-03-01T11:30:00.000Z"),
|
|
},
|
|
];
|
|
|
|
export const storybookSecretBindings: CompanySecretBinding[] = [
|
|
{
|
|
id: "binding-openai-agent",
|
|
companyId: "company-storybook",
|
|
secretId: "secret-openai",
|
|
targetType: "agent",
|
|
targetId: "agent-codex",
|
|
configPath: "env.OPENAI_API_KEY",
|
|
versionSelector: "latest",
|
|
required: true,
|
|
label: "Codex agent env",
|
|
createdAt: new Date("2026-03-02T09:00:00.000Z"),
|
|
updatedAt: new Date("2026-03-02T09:00:00.000Z"),
|
|
},
|
|
{
|
|
id: "binding-openai-project",
|
|
companyId: "company-storybook",
|
|
secretId: "secret-openai",
|
|
targetType: "project",
|
|
targetId: "project-app",
|
|
configPath: "env.OPENAI_API_KEY",
|
|
versionSelector: "latest",
|
|
required: true,
|
|
label: "Paperclip App project env",
|
|
createdAt: new Date("2026-03-02T09:00:00.000Z"),
|
|
updatedAt: new Date("2026-03-02T09:00:00.000Z"),
|
|
},
|
|
{
|
|
id: "binding-aws-environment",
|
|
companyId: "company-storybook",
|
|
secretId: "secret-aws-prod",
|
|
targetType: "environment",
|
|
targetId: "env-prod",
|
|
configPath: "secrets.AWS_DEPLOY",
|
|
versionSelector: 2,
|
|
required: true,
|
|
label: "Prod environment",
|
|
createdAt: new Date("2026-04-22T14:01:00.000Z"),
|
|
updatedAt: new Date("2026-04-22T14:01:00.000Z"),
|
|
},
|
|
];
|
|
|
|
export const storybookSecretAccessEvents: SecretAccessEvent[] = [
|
|
{
|
|
id: "evt-1",
|
|
companyId: "company-storybook",
|
|
secretId: "secret-openai",
|
|
version: 3,
|
|
provider: "local_encrypted",
|
|
actorType: "agent",
|
|
actorId: "agent-codex",
|
|
consumerType: "agent",
|
|
consumerId: "agent-codex",
|
|
configPath: "env.OPENAI_API_KEY",
|
|
issueId: "issue-storybook-1",
|
|
heartbeatRunId: "run-storybook",
|
|
pluginId: null,
|
|
outcome: "success",
|
|
errorCode: null,
|
|
createdAt: recent(12),
|
|
},
|
|
{
|
|
id: "evt-2",
|
|
companyId: "company-storybook",
|
|
secretId: "secret-openai",
|
|
version: 3,
|
|
provider: "local_encrypted",
|
|
actorType: "system",
|
|
actorId: null,
|
|
consumerType: "project",
|
|
consumerId: "project-app",
|
|
configPath: "env.OPENAI_API_KEY",
|
|
issueId: null,
|
|
heartbeatRunId: null,
|
|
pluginId: null,
|
|
outcome: "success",
|
|
errorCode: null,
|
|
createdAt: recent(48),
|
|
},
|
|
{
|
|
id: "evt-3",
|
|
companyId: "company-storybook",
|
|
secretId: "secret-openai",
|
|
version: null,
|
|
provider: "local_encrypted",
|
|
actorType: "agent",
|
|
actorId: "agent-codex",
|
|
consumerType: "agent",
|
|
consumerId: "agent-codex",
|
|
configPath: "env.OPENAI_API_KEY",
|
|
issueId: "issue-storybook-1",
|
|
heartbeatRunId: "run-storybook",
|
|
pluginId: null,
|
|
outcome: "failure",
|
|
errorCode: "secret_disabled",
|
|
createdAt: recent(360),
|
|
},
|
|
];
|
|
|
|
export const storybookSecretProviderHealth = {
|
|
providers: [
|
|
{
|
|
provider: "local_encrypted" as const,
|
|
status: "ok" as const,
|
|
message: "Encryption key loaded; permissions OK.",
|
|
warnings: [] as string[],
|
|
backupGuidance: ["Backup ~/.paperclip/instances/default/secrets/key separately from the database."],
|
|
},
|
|
{
|
|
provider: "aws_secrets_manager" as const,
|
|
status: "warn" as const,
|
|
message: "Connected; KMS key rotation policy not yet enforced.",
|
|
warnings: ["Set up automated KMS key rotation for production tenants."],
|
|
backupGuidance: [],
|
|
},
|
|
{
|
|
provider: "gcp_secret_manager" as const,
|
|
status: "ok" as const,
|
|
message: "Service account reachable.",
|
|
warnings: [] as string[],
|
|
backupGuidance: [],
|
|
},
|
|
{
|
|
provider: "vault" as const,
|
|
status: "ok" as const,
|
|
message: "KV v2 mount reachable.",
|
|
warnings: [] as string[],
|
|
backupGuidance: [],
|
|
},
|
|
],
|
|
};
|